Игровая программа "Судоку"
История судоку, правила игры и цель головоломки. Разработка диаграммы классов. Реализация программы в объектно-ориентированном стиле по принципам модульности, иерархичности, ограничения доступа. Алгоритм генерации случайного игрового поля судоку.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 01.02.2013 |
Размер файла | 315,9 K |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
ФЕДЕРАЛЬНОЕ АГЕНСТВО ПО ОБРАЗОВАНИЮ
Государственное образовательное учреждение высшего профессионального образования Белгородский государственный технологический университет им. В. Г. Шухова
Кафедра программного обеспечения вычислительной техники и автоматизированных систем
Курсовой проект по дисциплине
«Объектно-ориентированное программирование»
Выполнил
Студент группы ПВ-32
Артюх М.А.
Проверил
Ермоленко Д.Н.
Белгород 2010г.
Введение
В данном курсовом проекте представлена актуальная на сегодняшний день игра под названием судоку, реализованная в стиле объектно-ориентированного программирования.
Что же это за игра и как в неё играть?
История судоку
Прообраз современного судоку, так называемые "магические квадраты" знали еще в древнем Китае. В Европе вспоминается что-то подобное в XVIII веке, когда слепой швейцарский математик Леонард Эйлер (Leonhard Euler) выяснил, что в матрице размером 9х9 каждый ряд и каждую колонку можно заполнить цифрами от 1 до 9 в определенном порядке и без повторения.
Впервые судоку в современном виде появилась в одном из американских журналов кроссвордов в 1979 году. Автором головоломки был гражданин США, 74 летний архитектор на пенсии Howard Garns. Издатель - журнал „Math Puzzles and Logic Problems” дал пазлу имя „Number Place”. Настоящую популярность головоломка завоевала в 2005, когда японский журнал Nikoli стал регулярно печатать ее на своих страницах.
В 2004 Судоку начали печатать английские газеты, оттуда судоку-мания нахлынула на Европу и в Австралию. Наконец, в 2005 эта головоломка триумфально вернулась в США, завершив свой "кругосветный тур". В настоящее время выдается множество специализированных журналов и сборников, книг и инструкций по их решению, много газет печатают судоку вместе с кроссвордами и заданиями по шахматам судоку - это невероятно увлекательная логическая игра. Не подумайте, судоку это не новый кроссворд. Для того, чтобы играть в судоку не надо сидеть в библиотеке и искать нужное слово в энциклопедии. В судоку вообще нет слов. В судоку есть только цифры.
Судоку - это квадрат размером 9x9. Он разделен на 9 небольших квадратиков 3x3. В некоторых клетках в начале игры стоят числа от 1 до 9. Цель игры - заполнить пустые клетки по специальному правилу. Это задача может быть и простой и невозможно сложной, в зависимости от предложенного варианта. А вариантов в судоку может быть много. Невообразимо много - 6,670,903,752,021,072,936,960!
В Судоку хорошо играть в транспорте по дороге на работу или домой. Для судоку не нужен компьютер. В судоку можно играть, используя бумагу и ручку. Поверьте, время в пути уменьшится в десятки раз!
Само слово «судоку» имеет японские корни. Как-то в пятидесятые годы прошлого века в Японию попал американский журнал «Number Place», с опубликованными в нем необычными головоломками, для решения которых требовалось всего лишь правильно расставить цифры по позициям. Впоследствии благодаря данному словосочетанию, буквально переведенному на японский язык («су» - число, цифра; «доку» - позиция, место), возникло это новое сложное слово, которое много лет спустя, триумфально шествуя по миру, добралось-таки до наших краев.
Правила игры в судоку
Решение судоку - процесс творческий, требующие способности к логическому мышлению и определенных комбинаторных навыков. Со временем приходит опыт и каждый игрок разрабатывает для себя собственную стратегию.
Правила игры судоку совершенно просты. Игровое поле судоку состоит из 81 клетки, находящихся в 9 столбцах, 9 строках и 9 малых квадратах. Это собственно и есть магический квадрат судоку. В зависимости от уровня сложности некоторые клетки уже содержат числа. Ваша задача - заполнить остальные клетки, используя Ваши серые клеточки. Необходимо обратить внимание на следующее правило: В игре участвую только числа с 1 до 9. Игровое поле (квадрат 9x9) должен быть заполнен таким образом, что, каждое число (с 1 до 9) встречается в каждой строке, в каждом столбце и в каждом малом квадрате (3x3) только один-единственный раз.
Цель головоломки - необходимо заполнить свободные ячейки цифрами от 1 до 9 так, чтобы в каждой строке, в каждом столбце и в каждом малом квадрате 3х3, каждая цифра встречалась только один раз. Правильная головоломка имеет одно решение.
В последнее время появились и другие - более сложные модификации, чем 9х9 ячеек кроссвордов. Существуют судоку с размерами 15х15 или даже 16х16, предназначенные для опытных игроков. Для детей используются судоку меньших размеров, например, 2х2.
Как начать играть?
Начните с единицы. "Осмотритесь" сначала на игровом поле, найдя все клетки с цифрой 1. Проверьте каждый из малых квадратов (3x3), содержит ли он уже единицу. Попытайтесь разыскать все клетки внутри этого малого квадрата, в котором могла бы стоять единица. Не забывайте при этом о главном правиле: каждое число может, стоят в каждой строке, в каждом столбце и каждом маленьком квадрате только один раз. При этом нужно исключить все те клетки, в которых единица не может находиться, потому что столбец или строка или квадрат уже "заняты". Вполне вероятно, что в каком-либо из рассмотренных квадратов останется как раз одна клетка, в которой может находиться единица. Если Вы не уверены, что это число возможно только в этой клетке и нигде более, лучше всего оставить этот квадрат и попробовать с другим. Что-нибудь подходящее найдется непременно!
Проверьте, таким образом, все квадраты (3x3). Конечно, имеет смысл искать только там, где единица уже не стоит! После того, как Вы пройдетесь по всем квадратам с 1, повторите поиск с другим числом. Например, с двойкой. Потом с тройкой и так далее. До тех пор, пока Вы не проверили все цифры от 1 до 9. Вы увидите, что Вы заполнили уже очень много клеток. После чего, советуем "провернуть" всю процедуру еще раз с начала - снова от 1 до 9. Вы заметите, что дело идёт уже легче, потому что многие клетки Вы уже заполнили. И вы заметите, что там, где Вы раньше сомневались, теперь Вы уверенно можете ставить Ваше число.
Что представлено в курсовом проекте?
В курсовом проекте представлена игровая программа, способная составлять судоку и решать его на любом этапе игрового процесса. Программа может сохранять и загружать ранее сохраненную игру.
Также представлены все описания этапов анализа, разработки и отладки программы.
Постановка задачи
Разработать и программно реализовать игру «Судоку» в объектно-ориентированном стиле. В программе должны соблюдаться принципы информационной закрытости, модульности и иерархической организации.
Игра должна иметь:
1. Алгоритм решения произвольного игрового поля и уже заданной игры судоку.
2. Алгоритм генерации случайного игрового поля судоку.
3. Windows-приложение для вывода игрового поля на экран.
4. Возможность сохранения текущей игры и загрузки ранее сохраненной игры.
Анализ предметной области
Объектная декомпозиция:
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Разработка диаграммы классов
Размещено на http://www.allbest.ru/
Размещено на http://www.allbest.ru/
Данные классы находятся в следующих отношениях:
1. Ассоциация. Мощность: «один ко многим»
2. Наследование. Класс TGameSudoku наследует класс TSudoky.
3. Агрегация. Класс Matrix находится в отношении агрегации с классом TSudoky.
4. Зависимость. Класс Matrix находится в отношении зависимости с классом TSudoky.
Описание программной реализации
Программа была реализована в среде разработки Delphi 2010 (VCL Form Application), включает в себя тир модуля: WorkWithMatrix, Sudoky, GameSudoky.
В Модуле WorkWithMatrix реализован класс Matrix, который имеет описание всех структур данных, необходимых для реализации программы, и описание методов работы с этими структурами.
unit WorkWithMatrix;
interface
type Matrix=class
public
const n=9;
type t_mas= array [1..n] of byte;
t_matr=array [1..n] of t_mas; // собственно само судоку
t_set=set of 1..n; // множество
t_mas_set=array [1..n] of t_set; //массив множеств для проверки на повторы
t_mas_boolen=array [1..matrix.n] of boolean; //массив флагов
t_matr_boolean=array [1..matrix.n] of t_mas_boolen; //матрица флагов
public
procedure Sdvig(var s:t_matr; i:Byte); //сдвиг 3 строк на 1 шаг вправо
procedure sdvig2(var s:t_matr;i:byte); //сдвиг одной строки на 1 шаг вправо
procedure ZeroBoolMatr(var b:T_matr_boolean); //обнуление булевой матрицы
function IfMatrHavNull(s:T_matr):boolean;//проверяет имеет ли матрица хотябы один ноль
end;
В классе Matrix описаны типы:
1. целочисленный массив из n элементов(t_mas);
2. целочисленная матрица размером NxN(t_matr);
3. множество, которое может включать в себя элементы от 1 до n (t_set);
4. массив множеств из n множеств(t_mas_set);
5. массив типа Boolean из n элементов (t_mas_boolen);
6. матрица из элементов типа Boolean размером NxN(t_matr_boolean).
В классе Matrix описана константа (const n=9), которая обозначает размер судоку.
В классе Matrix описаны методы:
1. сдвиг 3-х строк в матрице s с позиции i на один шаг вправо(Sdvig);
2. сдвиг строки i в матрице s на один шаг вправо(Sdvig2);
3. обнуление матрицы, элементы которой типа Boolean(ZeroBoolMatr);
4. возвращает true если в матрице s есть хотябы один ноль, иначе false;
Класс Мatrix отображает в себе те действия над структурами, которые не имеют посредственного отношения к предметной области задачи, но используются при реализации других классов.
В модуле Sudoky реализован класс TSudoky. В этом классе реализованы поля и медоды для работы с судоку, как с математической моделью.
unit Sudoky;
interface
Uses windows,Classes,WorkWithMatrix;
type TSudoky=class
Sud:Matrix.t_matr;
GameSud:Matrix.t_matr;
Ans:array of Matrix.t_matr; //массив ответов из судоку
Mlen:integer;// количество решений в массиве Ans
Matr:matrix;
Public
constructor create();
destructor done();
procedure SudAddAns( s:matrix.t_matr);//добавляем судоку в массив ответов
function SudMod(var s:matrix.t_matr;var p:Tpoint;v:integer):Matrix.t_matr;// замена в судоку s одного значения v на позиции P
function IsNextUnknown( s:matrix.t_matr; var p:Tpoint):boolean; //находим в судоку пустую ячейку и возвращаем позицию P,иначе False;
function SudInLine(s:matrix.t_matr;var p:Tpoint;v:integer):boolean;//проверка по строке
function SudInRow( s:matrix.t_matr;var p:Tpoint;v:integer):boolean; //проверка по столбцу
function SudInSq( s:matrix.t_matr;var p:Tpoint;v:integer):boolean; //проверка в квадрате
function SudInAny( s:matrix.t_matr;var p:Tpoint;v:integer):boolean; //общая проверка на постановку числа
function DoRec( S:Matrix.t_matr):boolean;//рекурсивное построение судоку
function SudOK(s:Matrix.t_matr):boolean;// проверка на правильность построенного судоку
procedure generate(var s:matrix.t_matr); // генерирование судоку быстрым методом c возможным повторением
procedure generate_matr(var s:matrix.t_matr);//генерирует матрицу без повторений
procedure Random_generate( var s,b:matrix.t_matr); // генерация игрового судоку
procedure SetValInSud(var s:matrix.t_matr;i,j:byte; v:byte); //установка значения
end;
В классе TSudoky описаны поля:
1. Сгенерированное судоку(Sud);
2. Игровое судоку (GameSud);
3. Массив ответов из судоку(Ans);
4. Количество решений в массиве ответов из судоку(Mlen);
5. Переменная для использования методов из класса Matrix(Matr);
В классе TSudoky описаны методы:
1. инициализация полей класса(create);
2. удаление значений полей класса(done);
3. добавляем судоку s в массив Ans ответов(SudAddAns);
4. замена в судоку s одного значения v на позиции P (SudMod);
5. возвращает true, если в судоку s есть пустая ячейка, возвращение позиции P,иначе False(IsNextUnknown);
6. возвращает true, если в судоку s строка имеет правильное построение, иначе fase(SudInLine);
7. возвращает true, если в судоку s столбец имеет правильное построение, иначе fase(SudInRow);
8. возвращает true, если в судоку s квадрат имеет правильное построение, иначе fase(SudInSq);
9. возвращает true, если в судоку s квадрат, столбец и строка имеет правильное построение, иначе fase(SudInAny);
10. возвращает true, если рекурсивное построение судоку закончено верно, массив ответов Ans пополнен, иначе false(DoRec);
11. возвращает true, если судоку построено верно, иначе false(SudOK);
12. генерирование судоку быстрым методом c возможным повторением(generate);
13. генерирование судоку без повторений(generate_matr);
14. установка в судоку s значения v на позицию [i,j]( SetValInSud);
В модуле GameSud реализован класс TGameSud. В этом классе реализованы поля и медоды для работы с судоку как с игрой.
unit GameSud;
interface
Uses Sudoky,WorkWithMatrix;
type TGameSudoky=class(Tsudoky)
Adres:string; //адресс куда будет сохранена игра
Viz: matrix.t_matr_boolean; // матрица флагов видимости числел на игровом поле
User:matrix.t_matr_boolean; //матрица флагов введенных пользователем значений
UsersPointer:matrix. t_matr_boolean;//матрица флагов выделенных пользователем клеток
public
constructor Create;
destructor Done;
procedure Save(s:matrix.t_matr); //сохранение игры
procedure Load(var s:matrix.t_matr;var u:matrix.t_matr_boolean); //загрузка игры
procedure SudVizibleOnField(s:matrix.t_matr;var b:matrix.t_matr_boolean);//заполняет матрицу флагов видимости в соответствии с матрицой S
function SudVizible(V:matrix.t_matr_boolean;i,j:byte):boolean;//Должно ли число отображаться на экран
procedure Nulling(var b:matrix.t_matr_boolean); //обнуление матрицы флагов введенных пользователем значений
function SudIsFulling(s:matrix.t_matr):boolean; // заполнена ли судоку до конца
end;
В классе TGameSudoky описаны поля:
1. адрес, куда будет сохранена игра(Adres);
2. матрица флагов видимости чисел на игровом поле(Viz);
3. матрица флагов введенных пользователем значений(User);
4. матрица флагов выделенных пользователем клеток(UsersPointer);
В классе TGameSudoky описаны методы:
1. сохранение судоку s и матрицы флагов введенных пользователем значений User в текстовый файл по адресу Adres(Save);
2. загрузка судоку s и матрицы флагов введенных пользователем значений User из текстового файла по адресу Adres(Save);
3. заполняет матрицу флагов видимости User в соответствии с матрицей S (SudVizibleOnField);
4. обнуление матрицы флагов введенных пользователем User значений (Nulling);
5. возвращает true, если судоку s заполнена до конца (SudIsFulling);
6. возвращает true, если число v должно отображаться на экран (SudVizible);
головоломка судоку алгоритм модульность
Текст программы
unit Game;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,GameSud,WorkWithMatrix,Sudoky, Menus, ExtDlgs;
const T=51;
L=25;
type
TForm2 = class(TForm)
Image1: TImage;
Panel1: TPanel;
ComboBox1: TComboBox;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
MainMenu1: TMainMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
SaveDialog1: TSaveDialog;
OpenDialog1: TOpenDialog;
procedure FormCreate(Sender: TObject);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure N4Click(Sender: TObject);
procedure N2Click(Sender: TObject);
procedure N3Click(Sender: TObject); // возвращает позицию в матрице после нажптия мыши
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
S:TGameSudoky;
i,j:Byte; //Координаты текущего эдемента в матрице
implementation
{$R *.dfm}
procedure CreateFild(var cl:TColor);
var
I,J,k1,k2: Integer;
begin
k1:=0; k2:=0;
for I := 1 to matrix.n do
begin
k1:=0;
for j := 1 to matrix.n do
begin
form2.Image1.Canvas.Brush.Color:=cl;//clSkyBlue;
form2.image1.Canvas.Rectangle(0+k1,0+k2,50+k1,50+k2);
k1:=k1+T;
if j mod 3=0 then k1:=k1+5;
end;
k2:=k2+T;
if i mod 3=0 then k2:=k2+5;
end;
end;
procedure WriteSud;
var k1,k2:integer;
cl:Tcolor;
begin
cl:= clSkyBlue;
createFild(cl);
k1:=0; k2:=0;
for I := 1 to matrix.n do
begin
k1:=0;
for j := 1 to matrix.n do
begin
if s.GameSud[i,j]<>0 then
begin
form2.Image1.Canvas.Font.Style:=[fsBold];
form2.Image1.Canvas.Font.Size:=12;
form2.Image1.Canvas.Font.Color:=clBlue;
form2.image1.Canvas.TextOut(l+k1,l+k2,IntTostr(s.GameSud[i,j]));
if s.User[i,j]=true then
begin
form2.Image1.Canvas.Font.Style:=[fsBold];
form2.Image1.Canvas.Font.Size:=12;
form2.Image1.Canvas.Font.Color:=clRed;
form2.image1.Canvas.TextOut(l+k1,l+k2,IntTostr(s.GameSud[i,j]));
end;
end;
k1:=k1+T;
if j mod 3 =0 then k1:=k1+5;
end;
k2:=k2+T;
if i mod 3 =0 then k2:=k2+2;
end;
end;
procedure TForm2.Button1Click(Sender: TObject);
var z:byte;
begin
z:=form2.ComboBox1.ItemIndex;
if z<>255 then
begin
s.SetValInSud(s.GameSud,i,j,z);
s.DoRec(s.GameSud);
s.User[i,j]:=true;
s.UsersPointer[i,j]:=not (s.UsersPointer[i,j]);
end
else z:=0;
writesud;
end;
procedure TForm2.Button2Click(Sender: TObject);
var cl:Tcolor;
begin
s.Nulling(s.User);
s.Random_generate(s.Sud,s.GameSud);
s.SudVizibleOnField(s.GameSud,s.Viz);
cl:= clSkyBlue;
CreateFild(cl);
writesud;
end;
procedure TForm2.Button3Click(Sender: TObject);
var l:integer;
f:boolean;
begin
f:=s.IsValidSudoky(s.GameSud);
s.Ans:=nil;
s.Mlen:=100;
s.DoRec(s.GameSud);
l:= length(s.Ans);
if f=True then
begin
if l<>0 then
showmessage('Вы на верном пути!! ;)'+'Возможных решений:'+inttostr(l))
else showmessage('Вы ошиблись!!!');
end
else showmessage('Вы ошиблись!!!');
end;
procedure TForm2.Button4Click(Sender: TObject);
var f:boolean;
begin
f:=s.SudIsFulling(s.GameSud);
if f=false then showmessage('Поле не заполнено до конца!!!')
else
begin
if s.SudOK(s.GameSud)=false then Showmessage('Верно')
else Showmessage('Неверно');
end;
end;
procedure TForm2.FormCreate(Sender: TObject);
var cl:TColor;
begin
S:=TGameSudoky.Create;
s.Random_generate(s.Sud,s.GameSud);
s.Ans:=nil;
s.Mlen:=100;
s.DoRec(s.GameSud);
s.SudVizibleOnField(s.GameSud,s.Viz);
cl:= clSkyBlue;
CreateFild(cl);
writesud;
end;
procedure PaintRec( cl:Tcolor);
var k1,k2,i2,j2:integer;
begin
k1:=0; k2:=0;
for I2 := 1 to matrix.n do
begin
k1:=0;
for j2 := 1 to matrix.n do
begin
if (i=i2)and(j=j2)and(s.Viz[i,j]=false) then
begin
s.UsersPointer[i,j]:=not (s.UsersPointer[i,j]);
if s.UsersPointer[i,j]=true then
begin
cl:= clSkyBlue;
form2.Image1.Canvas.Brush.Color:=cl;
form2.image1.Canvas.Rectangle(0+k1,0+k2,50+k1,50+k2);
end
else
begin
form2.Image1.Canvas.Brush.Color:=cl;
form2.image1.Canvas.Rectangle(0+k1,0+k2,50+k1,50+k2);
end;
if (s.User[i,j]=true) then
begin
form2.Image1.Canvas.Font.Style:=[fsBold];
form2.Image1.Canvas.Font.Size:=12;
form2.Image1.Canvas.Font.Color:=clRed;
form2.image1.Canvas.TextOut(l+k1,l+k2,IntTostr(s.GameSud[i,j]));
end;
end;
k1:=k1+T;
if j2 mod 3=0 then k1:=k1+5;
end;
k2:=k2+T;
if i2 mod 3=0 then k2:=k2+5;
end;
end;
procedure TForm2.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
Var x1,y1,x2,y2,k1,k2,i2,j2:integer;
cl:Tcolor;
begin
x1:=0;x2:=T-1;j:=1;i:=1; y1:=0;y2:=t;
while (j<=matrix.n)and not((x1<x)and(x<x2)) do
begin
x1:=x1+T;
x2:=x2+T;
j:=j+1;
if j mod 3=0 then
begin
x1:=x1+5;
x2:=x2+5;
end;
end;
while (i<=matrix.n)and not((y1<y)and(y<y2)) do
begin
y1:=y1+T;
y2:=y2+T;
i:=i+1;
if i mod 3=0 then
begin
y1:=y1+5;
y2:=y2+5;
end;
end;
cl:=clgraytext;
PaintRec(cl);
end;
procedure TForm2.N2Click(Sender: TObject);
begin
if form2.SaveDialog1.Execute() then
begin
s.Adres:=form2.SaveDialog1.FileName;
s.Save(s.GameSud);
end;
end;
procedure TForm2.N3Click(Sender: TObject);
var cl:TColor;
begin
if form2.OpenDialog1.Execute then
begin
if form2.OpenDialog1.FileName<>'' then
begin
s.Adres:= form2.OpenDialog1.FileName;
s.Load(s.GameSud,s.User);
cl:= clSkyBlue;
CreateFild(cl);
writesud;
end;
end;
end;
procedure TForm2.N4Click(Sender: TObject);
begin
form2.Close;
end;
end.
unit Sudoky;
interface
Uses windows,Classes,WorkWithMatrix;
type TSudoky=class
Sud:Matrix.t_matr;
GameSud:Matrix.t_matr;
Ans:array of Matrix.t_matr; //массив ответов из судоку
Mlen:integer;// количество решений в массиве Ans
Matr:matrix;
Public
constructor create();
destructor done();
procedure SudAddAns( s:matrix.t_matr);//добавляем судоку в массив ответов
function SudMod(var s:matrix.t_matr;var p:Tpoint;v:integer):Matrix.t_matr;// замена в судоку s одного значения v на позиции P
function IsNextUnknown( s:matrix.t_matr; var p:Tpoint):boolean; //нахотим в судоку пустую ячейку и возвращаем позицию P,иначе False;
function SudInLine(s:matrix.t_matr;var p:Tpoint;v:integer):boolean;//проверка по строке
function SudInRow( s:matrix.t_matr;var p:Tpoint;v:integer):boolean; //проверка по столбцу
function SudInSq( s:matrix.t_matr;var p:Tpoint;v:integer):boolean; //проверка в квадрате
function SudInAny( s:matrix.t_matr;var p:Tpoint;v:integer):boolean; //общая проверка на постановку числа
function DoRec( S:Matrix.t_matr):boolean;//рекурсивное построение судоку
function SudOK(s:Matrix.t_matr):boolean;// проверка на правильность построенного судоку
procedure generate(var s:matrix.t_matr); // генерирование судоку быстрым методом c возможным повторением
procedure generate_matr(var s:matrix.t_matr);//генерирует матрицу без повторений
procedure Random_generate( var s,b:matrix.t_matr); // генерация игрового судоку
procedure SetValInSud(var s:matrix.t_matr;i,j:byte; v:byte); //установка значения
Function IsValidSudoky(s:matrix.t_matr):boolean; //проверка судоку на правильность
end;
implementation
procedure TSudoky.SetValInSud(var s: Matrix.t_matr; i: Byte; j: Byte; v: Byte);
begin
s[i,j]:=v;
end;
function TSudoky.sudInLine;
var
i:1..9;
begin
Result:=True;
for i:=1 to 9 do
if p.y<>i then
if s[p.X,i]=v then Exit;
Result:=False;
end;
function TSudoky.sudInRow;
var
i:1..9;
begin
Result:=True;
for i:=1 to 9 do
if p.x<>i then
if s[i,p.Y]=v then Exit;
Result:=False;
end;
function TSudoky.sudInSq;
var
ix,iy:0..8;
lx,ly:0..8;
begin
lx:=0; ly:=0;
if p.x in [1,2,3] then lx:=1;
if p.x in [4,5,6] then lx:=4;
if p.x in [7,8,9] then lx:=7;
lx:=lx-1;
if p.y in [1,2,3] then ly:=1;
if p.y in [4,5,6] then ly:=4;
if p.y in [7,8,9] then ly:=7;
ly:=ly-1;
Result:=True;
for ix:=1 to 3 do
for iy:=1 to 3 do
if (p.x<>lx+ix) and (p.y<>ly+iy) then
if s[lx+ix,ly+iy]=v then Exit;
Result:=False;
end;
function TSudoky.sudInAny;
begin
Result:=sudInLine(s,p,v) or sudInRow(s,p,v) or sudInSq(s,p,v);
end;
function TSudoky.IsNextUnknown;
var
ix,iy:1..9;
begin
Result:=False;
for ix:=1 to 9 do
for iy:=1 to 9 do
if s[ix,iy]=0 then begin
Result:=True;
p.X:=ix;
p.Y:=iy;
Exit;
end; // if
end;
function TSudoky.sudMod;
var
st:Matrix.t_matr;
begin
st:=s;
st[p.x,p.y]:=v;
Result:=st;
end;
procedure TSudoky.sudAddAns;
var
l:integer;
begin
l:=Length(ans);
SetLength(ans,l+1);
ans[l]:=s;
end;
function TSudoky.DoRec;
var
i:integer;
p:TPoint;
begin
Result:=True;
if IsNextUnknown(s,p) then begin // запуск рекурсий
for i:=1 to 9 do
if not sudInAny(s,p,i) then
if DoRec(sudMod(s,p,i)) then
Exit;
end else begin // сохранение результата
sudAddAns(s);
end;
if Length(ans)<mlen then // не хватает результатов
Result:=False;
end; // DoRec
function Tsudoky.IsValidSudoky(s:matrix.t_matr):boolean;
var
ix,iy:integer;
p:TPoint;
begin
for ix:=1 to 9 do
for iy:=1 to 9 do begin
p.X:=ix;
p.Y:=iy;
if s[ix,iy] <> 0 then
if sudInAny(s,p,s[ix,iy]) then begin
Result:=False;
Exit;
end; // if
end; // for
Result:=True;
end;
constructor Tsudoky.Create;
var i,j:integer;
begin
for I := 1 to matrix.n do
for j := 1 to matrix.n do sud[i,j]:=0;
end;
destructor Tsudoky.Done;
var i,j:integer;
begin
for I := 1 to matrix.n do
for j := 1 to matrix.n do sud[i,j]:=0;
end;
function Tsudoky.SudOK(s: matrix.t_matr):boolean;
var i,j,z1,z2,t:integer;
flag:boolean;
begin
flag:=false;
i:=1;
j:=1;
while (j<=matrix.n)and(flag = false) do
begin
i:=1;
while (i<=matrix.n)and(flag = false) do
begin
z1:=i+1;
z2:=j+1;
t:=s[i,j];
while (z1<=matrix.n)and(flag=false) do
begin
if t=s[z1,j] then flag:=true;
z1:=z1+1;
end;
while (z2<=matrix.n)and(flag=false) do
begin
if t=s[i,z2] then flag:=true;
z2:=z2+1;
end;
i:=i+1;
end;
j:=j+1;
end;
result:=flag;
end;
procedure tsudoky.generate(var s: matrix.t_matr);
var i,j,k,z:byte;
m:matrix.t_set;
t:matrix.t_mas_set;
flag:boolean;
b:matrix.t_matr;
begin
randomize;
m:=[];
j:=1; i:=1;
while j<=matrix.n do begin
k:=random (matrix.n)+1;
if not(k in m) then begin
s[i,j]:=k;
m:=m+[k];
t[j]:=t[j]+[k];
j:=j+1;
end;
end;
for i:=2 to 3 do matr.Sdvig(s,i);
for i:=2 to 3 do
for j:=1 to matrix.n do t[j]:=t[j]+[s[i,j]];
i:=4;
matr.sdvig(s,i);
for j:=1 to matrix.n do
begin
begin
if (s[i,j] in t[j]) then
matr.sdvig2(s,i);
end;
end;
for i:=5 to 6 do matr.sdvig(s,i);
for i:=5 to 6 do
for j:=1 to matrix.n do t[j]:=t[j]+[s[i,j]];
i:=7;
matr.sdvig(s,i);
for j:=1 to matrix.n do
begin
begin
if (s[i,j] in t[j]) then
matr.sdvig2(s,i);
end;
end;
for i:=8 to 9 do matr.sdvig(s,i);
end;
procedure tsudoky.generate_matr(var s: matrix.t_matr);
var flag:boolean;
begin
repeat
begin
generate(s);
flag:=SudOK(s);
end;
until(flag=false);
end;
procedure tsudoky.Random_generate( var s,b: matrix.t_matr);
var i,j,k:integer;
f:boolean;
//s:t_matr;
begin
randomize;
generate_matr(s);
for I := 1 to matrix.n do
for j := 1 to matrix.n do
begin
k:=random(2)+1;
if k=1 then
begin
b[i,j]:=s[i,j];
end
else b[i,j]:=0;
end;
end;
end.
unit GameSud;
interface
Uses Sudoky,WorkWithMatrix;
type TGameSudoky=class(Tsudoky)
Adres:string; //адресс куда будет сохранена игра
Viz: matrix.t_matr_boolean; // матрица флагов видимости числел на игровом поле
User:matrix.t_matr_boolean; //матрица флагов введенных пользователем значений
UsersPointer:matrix. t_matr_boolean;//матрица флагов выделенных пользователем клеток
public
constructor Create;
destructor Done;
procedure Save(s:matrix.t_matr); //сохранение игры
procedure Load(var s:matrix.t_matr;var u:matrix.t_matr_boolean); //загрузка игры
procedure SudVizibleOnField(s:matrix.t_matr;var b:matrix.t_matr_boolean);//заполняет матрицу флагов видимости в соответствии с матрицой S
function SudVizible(V:matrix.t_matr_boolean;i,j:byte):boolean;//Должно ли число отображаться на экран
procedure Nulling(var b:matrix.t_matr_boolean); //обнуление матрицы флагов введенных пользователем значений
function SudIsFulling(s:matrix.t_matr):boolean; // заполнена ли судоку до конца
end;
implementation
constructor TGameSudoky.Create;
var i,j:byte;
begin
inherited create;
for I := 1 to matrix.n do
for j := 1 to matrix.n do
UsersPointer[i,j]:=false;
end;
function TGameSudoky.SudIsFulling(s: Matrix.t_matr):boolean;
var matr:matrix;
begin
result:= matr.IfMatrHavNull(s);
end;
procedure Tgamesudoky.Nulling(var b: Matrix.t_matr_boolean);
var Matr:matrix;
begin
matr.ZeroBoolMatr(b);
end;
destructor TGameSudoky.Done;
var i,j:byte;
begin
inherited Done;
Adres:='';
for I := 1 to matrix.n do
for j := 1 to matrix.n do
UsersPointer[i,j]:=false;
end;
procedure TGameSudoky.SudVizibleOnField(s: matrix.t_matr; var b: matrix.t_matr_boolean);
var i,j:byte;
begin
for I := 1 to matrix.n do
for j := 1 to matrix.n do
begin
if s[i,j]=0 then b[i,j]:=false
else b[i,j]:=true;
end;
end;
function TGameSudoky.SudVizible;
begin
result:= (v[i,j]=true);
end;
procedure TGameSudoky.Save(s: matrix.t_matr);
var f:text;
i,j:byte;
begin
assignfile(f,adres);
rewrite(f);
for I := 1 to matrix.n do
for j := 1 to matrix.n do
write(f,s[i,j]);
for I := 1 to matrix.n do
for j := 1 to matrix.n do
if user[i,j]=true then write(f,1) else write(f,0);
close(f);
end;
procedure TGameSudoky.Load;
var f:text;
i,j:byte;
c:char;
begin
assignfile(f,adres);
reset(f);
for I := 1 to matrix.n do
for j := 1 to matrix.n do
begin
read(f,c);
s[i,j]:=ord(c)-ord('0');
end;
for I := 1 to matrix.n do
for j := 1 to matrix.n do
begin
read(f,c);
if (ord(c)-ord('0'))=1 then u[i,j]:=true else u[i,j]:=false;
end;
close(f);
end;
end.
unit WorkWithMatrix;
interface
type Matrix=class
public
const n=9;
type t_mas= array [1..n] of byte;
t_matr=array [1..n] of t_mas; // собственно само судоку
t_set=set of 1..n; // множество
t_mas_set=array [1..n] of t_set; //массив множеств для проверки на повторы
t_mas_boolen=array [1..matrix.n] of boolean; //массив флагов
t_matr_boolean=array [1..matrix.n] of t_mas_boolen; //матрица флагов
public
procedure Sdvig(var s:t_matr; i:Byte); //сдвиг 3 строк на 1 шаг
procedure sdvig2(var s:t_matr;i:byte); //сдвиг одной строки на 1 шаг
procedure ZeroBoolMatr(var b:T_matr_boolean); //обнуление булевой матрицы
function IfMatrHavNull(s:T_matr):boolean;//проверяет имеет ли матрица хотябы один ноль
end;
implementation
function matrix.IfMatrHavNull(s: Matrix.t_matr):boolean;
var i,j:byte;
f:boolean;
begin
f:=true;i:=1;j:=1;
while (i<=n)and(f=true) do
begin
j:=1;
while(j<=n)and(f=true) do
begin
if s[i,j]=0 then f:=false;
j:=j+1;
end;
i:=i+1;
end;
result:=f;
end;
procedure Matrix.ZeroBoolMatr(var b: Matrix.t_matr_boolean);
var i,j:byte;
begin
for I := 1 to n do
for j := 1 to n do
b[i,j]:=false;
end;
procedure Matrix.Sdvig;
var b:T_matr;
begin
b[i,1]:=s[i-1,4];
b[i,2]:=s[i-1,5];
b[i,3]:=s[i-1,6];
s[i,1]:=s[i-1,7];
s[i,2]:=s[i-1,8];
s[i,3]:=s[i-1,9];
s[i,4]:=s[i-1,1];
s[i,5]:=s[i-1,2];
s[i,6]:=s[i-1,3];
s[i,7]:=b[i,1];
s[i,8]:=b[i,2];
s[i,9]:=b[i,3];
end;
procedure Matrix.sdvig2(var s: t_matr; i: Byte);
var j,z:byte;
begin
z:=s[i,1];
for j:=2 to n do
begin
s[i,j-1]:=s[i,j];
end;
s[i,n]:=z;
end;
end.
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Sudoky in 'Sudoky.pas',
GameSud in 'GameSud.pas',
WorkWithMatrix in 'WorkWithMatrix.pas';
procedure WriteSud(var s:matrix.t_matr);
var i,j:byte;
begin
for i := 1 to matrix.n do
begin
writeln;
for j := 1 to matrix.n do
begin
write(' ');
write (s[i,j]);
end;
end;
end;
procedure WriteMatrBool(var v:t_matr_boolean);
var i,j:byte;
begin
for i := 1 to matrix.n do
begin
writeln;
writeln;
for j := 1 to matrix.n do
begin
write(' ');
write (v[i,j]);
end;
end;
end;
var S:Tsudoky;
s1:TGameSudoky;
b:matrix.t_matr;
i,j,l:integer;
flag:boolean;
begin
s1:=TGameSudoky.Create;
s1.Adres:= 'C:\Users\91980\Desktop\Курсовой проект по ООП\Save.txt';
s1.Ans:=nil;
s1.Mlen:=100;
writeln('Generate sudoky:');
s1.Random_generate(s1.Sud,s1.GameSud);
writesud(s1.Sud);
writeln;
writeln;
writeln('Generate game sudoky:');
writesud(s1.GameSud);
writeln;
writeln;
s1.DoRec(s1.GameSud);
l:=length(s1.Ans);
writeln('Count of ansver:',' ',l);
writeln;
writeln;
writeln('Save in file');
s1.Save(s1.GameSud);
writeln;
writeln;
writeln('Load from file');
s1.Load(b);
writesud(b);
writeln;
writeln;
writeln('Matrix of vizible:');
s1.SudVizibleOnField(s1.GameSud,s1.Viz);
WriteMatrBool(s1.Viz);
readln;
readln;
end.
Как пользоваться приложением
Программа для игры в судоку имеет графический интерфейс.
В приложении реализована возможность ввода значения и его удаление. Для этого нужно выделить нужный квадрат (он отметится другим цветом), выбрать из списка значений нужное число и нажать кнопку «Ввод значения». После нажатия выбранное значение установится на выделенной клетке и будет красного цвета.
Также в программе имеется возможность проверки на любом этапе игрового процесса. Для этого имеется две кнопки: «Подсказка» и «Полная проверка». Кнопка «Подсказка» выводит на экран сообщение, которое содержит информацию: игрок правильно установил значение и количество возможных решений при заданном значении, или значение установлено неверно. Кнопка «Полная проверка» проверяет на правильность полностью заполненное поле. Если поле заполнено полностью, то появляется сообщение: выиграл пользователь или допустил ошибку. Если поле заполнено не до конца, то появляется сообщение «Поле не заполнено до конца!!!».
В реализации имеется также возможность сохранять текущую игру и загружать ранее сохраненную игру. Соответствующие кнопки для данных действий можно найти в меню: Файл ->Сохранить или Файл ->Загрузить.
В курсовом проекте был представлен принцип модульности: каждый класс описан в отдельном модуле. Это дает возможность использовать реализованные классы в других приложениях.
Также в курсовом проекте была реализована тестовая программа для визуальной проверки правильности описанных в классах алгоритмов. Тестовая программа использует те же модули, что и основная программа.
Заключение
В ходе выполнения курсовой работы были полностью реализованы поставленные цели и задачи, а именно:
1. Анализ предметной области задачи
2. Построение диаграммы объектов и диаграммы классов
3. Реализация программы в объектно-ориентированном стиле по принципам модульности, иерархичности, ограничения доступа.
Игра имеет:
1. Алгоритм решения произвольного игрового поля и уже заданной игры судоку.
2. Алгоритм генерации случайного игрового поля судоку.
3. Windows-приложение для вывода игрового поля на экран.
4. Возможность сохранения текущей игры и загрузки ранее сохраненной игры.
Список использованных источников
1. Лекции по дисциплине «Объектно-ориентированное программирование»
2. А.В. Серов - «Технологии Delphi»
3. С.А. Немнюгин -«Turbo Pascal»
Размещено на Allbest.ru
Подобные документы
История распространения "Судоку". Механизм решения и различия по уровню сложности в зависимости от размера квадрата данной головоломки. Освоение процесса создания программного продукта на Microsoft .NET Framework на языке C# на примере игры "Судоку".
курсовая работа [398,8 K], добавлен 21.10.2011Разработка программного продукта на языке Delphi, предназначенного для решения японской головоломки "Судоку": ознакомление с правилами игры, выбор необходимых компонент, написание алгоритмов реализации задачи; описание пользовательского интерфейса.
курсовая работа [3,5 M], добавлен 25.06.2011Написание игры "Lines" на языке Object Pascal в среде Delphi. Алгоритм работы программы. Описание метода генерации поля. Используемые константы и переменные. Форма приложения после старта игрового процесса. Основные элементы формы и обработки событий.
курсовая работа [225,0 K], добавлен 12.04.2012История создания игры "Тетрис", смысл и правила данной головоломки. Разработка поля игры и фигур тетрамино. Процедуры и функции, используемые для реализации движения фигур, их поворота и складывания в ряды, удаления и подсчета количества целых рядов.
курсовая работа [87,0 K], добавлен 02.02.2013Приемы программирования в Delphi. Алгоритм поиска альфа-бета отсечения, преимущества. Описание программного средства. Разработка программы, реализующая алгоритм игры "реверси". Руководство пользователя. Листинг программы. Навыки реализации алгоритмов.
курсовая работа [357,1 K], добавлен 28.02.2011Разработка программы логической игры в "крестики-нолики" пять в ряд на поле размера 15х15 клеток с применением графики на языке Pascal с использованием объектно-ориентированного программирования. Структура алгоритма программы и описание ее работы.
курсовая работа [821,5 K], добавлен 13.02.2012Создание игровой системы "Тетрис": количество игр, режимы сложности, интерфейс пользователя, игровая статистика, обработка исключений. Структура входных и выходных данных. Диаграммы и описание классов. Блок-схема алгоритма программы, результаты ее работы.
курсовая работа [1,9 M], добавлен 13.06.2012Игровая программа "шашки" для игры между человеком и компьютером. Разработка алгоритмов, историческая линия развития задач. Различные подходы к построению систем. Сокращенный листинг программы и описание алгоритма. Компоненты искусственного интеллекта.
курсовая работа [196,2 K], добавлен 26.03.2009Принципы построения информационной системы и ее реализация. Разработка программы доступа к данным автомобильного предприятия города на объектно-ориентированном языке программирования C Sharp. Расчет эффективности разрабатываемого програмного продукта.
дипломная работа [4,3 M], добавлен 15.05.2012Розробка програми GameBox, яка включає в себе дві гри, судоку та пятнашки. Опис структури даних та вимоги до них, процедур і функцій користувача, стандартних процедур і функцій, які використовувались в програмі, та файлів. Результати роботи програми.
курсовая работа [5,3 M], добавлен 12.11.2011