前言
这一段时间学了不少东西,想找个项目历练一下,就去牛客上翻了翻,看到这个我小时候经常玩的游戏,就想开发一下试试。因为第一次做项目,不知道如何做,就去牛客此项目下的评论区看了下别人的作品,发现算法有错,不能正常玩,决定自己开发一个能玩的游戏。
游戏介绍
数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足以下规则:
- 每一行的9个空格不重复的填放1~9的数字
- 每一列的9个空格不重复的填放1~9的数字
- 每一个粗线宫内的9个空格不重复的填放1~9的数字
数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1~9的数字。使1~9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。
设计思路
为了确保游戏能够正确的玩,即生成有效的地图。我将游戏的制作分成了两部分,游戏算法设计和文字界面设计。游戏算法设计是为了保证能生成有效地图,确保玩家玩的游戏有解。文字界面设计是为了让此游戏更美观,让玩家玩起了更舒适。
算法实现
为了确保生成有效地图,我将地图的9个宫进行标记。
按以下的算法生成有效的地图:
- 首先生成9*9的全排列,存储起来。存储方式采用char **initable;
- 生成一个在0~initable.size()-1之间的随机数,排放在’1’位置。
- 根据’1’位置,找出符合的’2’位置的数量,将下标放入vector query;
- 生成一个在0~query.size()-1之间的随机数,在initable中查找并放入’2’位置,清空query;
- 根据’1’、’2’位置找出符合’3’位置的个数,将下标放入query;
- 生成一个在0~query.size()-1之间的随机数,在initable中查找并放入‘3’位置,清空query;
- 同理找出’4’、’7’位置
- 根据’2’与’4’的位置找出符合’5’位置的个数,放入query;
- 生成一个在0~query.size()-1之间的随机数,在initable中查找并放入’5’位置,清空query;
- 根据’3’、‘4’、’5’确定’6’的位置的个数,放入vectorquery1;如果query1为空,返回第9步。否则执行第11步
- 根据’2’、‘5’、’7’确定’8’的位置的个数,放入vectorquery2;如果query2为空,返回第9步。否则执行第12步
- 对query1与query2进行嵌套循环,采用dfs查询在’9’的位置是否存在符合游戏规则的答案,如果没有符合规则的地图返回第2步。
文字界面
因为第一次做项目,对于文字界面完全是个小白,所以在开始项目的第一天我先学习了Linux的ncurses库。笔记链接:Linux下curses函数库的详细介绍
利用ncurses库设计了游戏界面,控制好光标即可,其他没什么好介绍的,看游戏源码即可。
总结
经过两天的努力,完成从设计到开发的全部过程,成果可见。游戏开发创新之处在于算法的设计,抛弃传统的随机地图生成算法,提出新的有效地图生成算法,新的算法速度可观,可在很快的时间内生成一副有效地图。
为了减少单个有效地图生成的时间,我将排列表的生成放在了init()函数内,其原因是生成排列表的时间在30ms以内,玩家按下s或着q的时间内,这个排列表已经完成。
因为第一次开发项目,对扩展性不太了解,所以这个游戏的可扩展性很差,目前我了解到一些提高可扩展性的方法,其中模板机智、常量定义等都是常用的方法。
游戏开发体会:对于算法问题需要仔细的思考;对于技术问题,需要认真的学习;对于代码,需要多加注释。
遇到的问题
在开发的过程中遇到了不少问题,汇总如下:
- static的理解:static的生命周期是进程。
- vector越界:代码中:0~query.size(); VS报错:vector subscript out of range。更改为:0~query.size()-1;
- 数组越界原因:由于定义char table[11][11],访问table[14][14]导致越界,错误提示:Run-Time Check Failure #2 – Stack around the variable ‘s’ was corrupted.
- ncurses中文字符使用:
4.1. 安装 sudo apt-get install libncursesw5 libncursesw5-dev
4.2. 使用setlocale函数设置locale setlocale(LC_ALL,””);
4.3. 编译 g++ sudo.o main.o -lncursesw -o main 使用-lncursesw链接 - sleep()函数:在头文件 unistd.h 中
- Linux中vim粘贴省略缩进:在vim中输入:set paste
- 类中数据成员的初始化问题:因为没有对curtable初始话,导致生成地图有误。
- 位置初始化:因为使用judgeans()导致当前光标移动,在跳出此函数时需要光标回到此位置。
- addch()函数:在添加字符之后光标向后移动一个,为了光标导航,需要光标调回原位置,即减一回到原位置。
- 删除字符剩余加一:游戏的输赢规则是根据剩余未填个数判断,当清空一个单元格的数字时,剩余字符加一。
给出源码之前在来一张游戏截图吧~~~
源码:
//main.cpp
#include<iostream>
#include<ctime>
#include<cstdio>
#include"sudo.h"
int main()
{
sudo s;
s.init();
s.run();
return 0;
}
#makefile
All:sudo.o main.o main clean
src = $(wildcard ./*.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
main:$(obj)
g++ $^ -lncursesw -o $@
%.o:%.cpp
g++ $< -c -o $@
clean:
rm -f $(obj)
//sudo.h
#pragma once
#include<vector>
using namespace std;
class sudo
{
public:
void init();//初始化游戏的界面
void inittable(int cnt);//初始化9*9全排列
int random(int L, int R);//生成随机数
void getcellr(int sx, int ex, int sy, int ey, int* hashr1, int* hashr2, int* hashr3);//获取行信息
void getcellc(int sx, int ex, int sy, int ey, int* hashc1, int* hashc2, int* hashc3);//获取列信息
int Nextcell(vector<int>& cellr, vector<int>& cellc);//根据目前的表格,查找下一个表格
void drawcell(int sx, int ex, int sy, int ey, int index);//绘制一个单元格
void setcell();//设置所有的单元格
bool judge(int x, int y, int k);//判断(x,y)位置放k是否可行
bool dfs(int cnt);//判断是否存在答案
void draw();//画游戏的图
bool judgeans(const int& my, const int& mx, char ch);//判断当前位置能否放ch
bool judgemove(const int& my, const int& mx, const int& cury, const int& curx);//判断当前位置是否越界
void run();//执行
void test();//测试
void printwin();//打印youwin
void printlost();//打印youlost
public:
sudo();
virtual ~sudo();
private:
char** initable;
int remind;//剩余个数
int numbers;
char** table;//答案地图
char** curtable;//当前地图的值不能清楚
};
//sudo.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cstddef>
#include<random>
#include<unistd.h>
#include<ctime>
#include <locale.h>
#include<ncurses.h>
#include<algorithm>
using namespace std;
#include "sudo.h"
const int MAX = 362879;
const int MIN = 0;
void sudo::test()//测试
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
printf("%c", table[i][j]);
printf("\n");
}
return;
}
/*
Welcome to Sudoku 17
Please enter s to start the game or q to exit game 50
author: 葫芦娃兄弟的混天绫 26
version:1.0.0 13
*/
void sudo::init()//初始化游戏的界面
{
setlocale(LC_ALL, "");
initscr();
cbreak();
noecho();
int y, x;
char ch;
getmaxyx(stdscr, y, x);
mvprintw(y / 2 - 1, (x - 17) / 2, "Welcome to Sudoku");
mvprintw(y / 2, (x - 50) / 2, "Please enter s to start the game or q to exit game");
mvprintw(y / 2 + 1, (x - 26) / 2, "author: 葫芦娃兄弟的混天绫");
mvprintw(y / 2 + 2, (x - 13) / 2, "version:1.0.0");
inittable(0);
ch = getch();
while (ch != 's' && ch != 'S')
{
if (ch == 'q' || ch == 'Q')
{
endwin();
exit(0);
}
beep();
ch = getch();
}
return;
}
void sudo::inittable(int cnt)//初始化9*9全排列
{
static bool used[11] = { false };
static char ttable[11];
if (cnt == 9)
{
ttable[cnt] = '\0';
strcpy(initable[numbers], ttable);
numbers++;
return;
}
for (int i = 1; i <= 9; i++)
{
if (!used[i])
{
used[i] = true;
ttable[cnt] = '0' + i;
inittable(cnt + 1);
ttable[cnt] = '\0';
used[i] = false;
}
}
}
int sudo::random(int L, int R)//生成随机数
{
static default_random_engine e(unsigned(time(0)));
uniform_int_distribution<unsigned> u(L, R);
return u(e);
}
void sudo::drawcell(int sx, int ex, int sy, int ey, int index)//绘制一个单元格
{
for (int i = sx; i < ex; i++)
{
for (int j = sy; j < ey; j++)
{
table[i][j] = *(*(initable + index) + (i - sx) * 3 + (j - sy));
}
}
return;
}
void sudo::getcellr(int sx, int ex, int sy, int ey, int* hashr1, int* hashr2, int* hashr3)//获取单元格行信息
{
for (int i = sx; i < ex; i++)
for (int j = sy; j < ey; j++)
{
if (i - sx == 0) hashr1[table[i][j] - '0']++;
else if (i - sx == 1)hashr2[table[i][j] - '0']++;
else if (i - sx == 2)hashr3[table[i][j] - '0']++;
}
}
void sudo::getcellc(int sx, int ex, int sy, int ey, int* hashc1, int* hashc2, int* hashc3)//获取单元格列信息
{
for (int i = sx; i < ex; i++)
for (int j = sy; j < ey; j++)
{
if (j - sy == 0) hashc1[table[i][j] - '0']++;
else if (j - sy == 1)hashc2[table[i][j] - '0']++;
else if (j - sy == 2)hashc3[table[i][j] - '0']++;
}
}
int sudo::Nextcell(vector<int>& cellr, vector<int>& cellc)//根据目前的表格,查找下一个表格
{
vector<int> query;//存放在query内
int hashr1[11] = { 0 }, hashr2[11] = { 0 }, hashr3[11] = { 0 };
int hashc1[11] = { 0 }, hashc2[11] = { 0 }, hashc3[11] = { 0 };
for (size_t i = 0; i < cellr.size(); i++)//获取哪一个单元格的行信息
{
switch (cellr[i])
{
case 1:
getcellr(0, 3, 0, 3, hashr1, hashr2, hashr3);
break;
case 2:
getcellr(0, 3, 3, 6, hashr1, hashr2, hashr3);
break;
case 3:
getcellr(0, 3, 6, 9, hashr1, hashr2, hashr3);
break;
case 4:
getcellr(3, 6, 0, 3, hashr1, hashr2, hashr3);
break;
case 5:
getcellr(3, 6, 3, 6, hashr1, hashr2, hashr3);
break;
case 6:
getcellr(3, 6, 6, 9, hashr1, hashr2, hashr3);
break;
case 7:
getcellr(6, 9, 0, 3, hashr1, hashr2, hashr3);
break;
case 8:
getcellr(6, 9, 3, 6, hashr1, hashr2, hashr3);
break;
}
}
for (size_t i = 0; i < cellc.size(); i++)//获取哪一个单元格的列信息
{
switch (cellc[i])
{
case 1:
getcellc(0, 3, 0, 3, hashc1, hashc2, hashc3);
break;
case 2:
getcellc(0, 3, 3, 6, hashc1, hashc2, hashc3);
break;
case 3:
getcellc(0, 3, 6, 9, hashc1, hashc2, hashc3);
break;
case 4:
getcellc(3, 6, 0, 3, hashc1, hashc2, hashc3);
break;
case 5:
getcellc(3, 6, 3, 6, hashc1, hashc2, hashc3);
break;
case 6:
getcellc(3, 6, 6, 9, hashc1, hashc2, hashc3);
break;
case 7:
getcellc(6, 9, 0, 3, hashc1, hashc2, hashc3);
break;
case 8:
getcellc(6, 9, 3, 6, hashc1, hashc2, hashc3);
break;
}
}
for (int i = 0; i <= MAX; i++)//根据获取的行列信息,确定满足当前3*3单元格的排列的个数及下标
{
bool flag = true;
for (int j = 0; j < 3; j++)
if (hashr1[initable[i][j] - '0'])
flag = false;
for (int j = 3; j < 6; j++)
if (hashr2[initable[i][j] - '0'])
flag = false;
for (int j = 6; j < 9; j++)
if (hashr3[initable[i][j] - '0'])
flag = false;
for (int j = 0; j < 9; j += 3)
if (hashc1[initable[i][j] - '0'])
flag = false;
for (int j = 1; j < 9; j += 3)
if (hashc2[initable[i][j] - '0'])
flag = false;
for (int j = 2; j < 9; j += 3)
if (hashc3[initable[i][j] - '0'])
flag = false;
if (flag)
query.push_back(i);
}
if (query.size() == 0)
return -1;
return query[random(0, query.size() - 1)];
}
void sudo::setcell()//设置单元格
{
vector<int> cellr;//存放需要查询的行单元格
vector<int> cellc;//存放需要查询的列单元格
int curorder[11] = { 0,1,2,3,4,7,5,6,8,9 };//排放单元格的顺序
int index = 0;
int cur = 1;
while (cur <= 7)
{
switch (curorder[cur])
{
case 1://排放‘1’
drawcell(0, 3, 0, 3, random(MIN, MAX));
cur++;
break;
case 2://排放‘2’
cellr.clear();
cellc.clear();
cellr.push_back(1);
index = Nextcell(cellr, cellc);
if (index == -1)
cur--;
else
{
drawcell(0, 3, 3, 6, index); cur++;
}
break;
case 3:
cellr.clear();
cellc.clear();
cellr.push_back(1);
cellr.push_back(2);
index = Nextcell(cellr, cellc);
if (index == -1)
cur--;
else
{
drawcell(0, 3, 6, 9, index); cur++;
}
break;
case 4:
cellr.clear();
cellc.clear();
cellc.push_back(1);
index = Nextcell(cellr, cellc);
if (index == -1)
cur--;
else
{
drawcell(3, 6, 0, 3, index); cur++;
}
break;
case 5:
cellr.clear();
cellc.clear();
cellr.push_back(4);
cellc.push_back(2);
index = Nextcell(cellr, cellc);
if (index == -1)
cur--;
else
{
drawcell(3, 6, 3, 6, index); cur++;
}
break;
case 7:
cellr.clear();
cellc.clear();
cellc.push_back(1);
cellc.push_back(4);
index = Nextcell(cellr, cellc);
if (index == -1)
cur--;
else
{
drawcell(6, 9, 0, 3, index); cur++;
}
break;
default:
vector<int> query6;//存放单元格6的方案
vector<int> query8;//存放单元格8的方案
//查找满足‘6’位置的单元格
int hashr1[11] = { 0 }, hashr2[11] = { 0 }, hashr3[11] = { 0 };
int hashc1[11] = { 0 }, hashc2[11] = { 0 }, hashc3[11] = { 0 };
getcellr(3, 6, 0, 3, hashr1, hashr2, hashr3);//查找‘4’
getcellr(3, 6, 3, 6, hashr1, hashr2, hashr3);//查找‘5’
getcellc(0, 3, 6, 9, hashc1, hashc2, hashc3);//查找‘3’
for (int i = 0; i <= MAX; i++)
{
bool flag = true;
for (int j = 0; j < 3; j++)
if (hashr1[initable[i][j] - '0'])
flag = false;
for (int j = 3; j < 6; j++)
if (hashr2[initable[i][j] - '0'])
flag = false;
for (int j = 6; j < 9; j++)
if (hashr3[initable[i][j] - '0'])
flag = false;
for (int j = 0; j < 9; j += 3)
if (hashc1[initable[i][j] - '0'])
flag = false;
for (int j = 1; j < 9; j += 3)
if (hashc2[initable[i][j] - '0'])
flag = false;
for (int j = 2; j < 9; j += 3)
if (hashc3[initable[i][j] - '0'])
flag = false;
if (flag)
query6.push_back(i);
}
if (query6.size() == 0)
{
cur--;
break;
}
//查找满足‘8’位置的单元格
for (int i = 0; i <= 10; i++)
hashr1[i] = hashr2[i] = hashr3[i] = hashc1[i] = hashc2[i] = hashc3[i] = 0;
getcellc(0, 3, 3, 6, hashc1, hashc2, hashc3);//查找‘2’
getcellc(3, 6, 3, 6, hashc1, hashc2, hashc3);//查找‘5’
getcellr(6, 9, 0, 3, hashr1, hashr2, hashr3);//查找‘7’
for (int i = 0; i <= MAX; i++)
{
bool flag = true;
for (int j = 0; j < 3; j++)
if (hashr1[initable[i][j] - '0'])
flag = false;
for (int j = 3; j < 6; j++)
if (hashr2[initable[i][j] - '0'])
flag = false;
for (int j = 6; j < 9; j++)
if (hashr3[initable[i][j] - '0'])
flag = false;
for (int j = 0; j < 9; j += 3)
if (hashc1[initable[i][j] - '0'])
flag = false;
for (int j = 1; j < 9; j += 3)
if (hashc2[initable[i][j] - '0'])
flag = false;
for (int j = 2; j < 9; j += 3)
if (hashc3[initable[i][j] - '0'])
flag = false;
if (flag)
query8.push_back(i);
}
if (query8.size() == 0)
{
cur--;
break;
}
bool fdfs = false;
for (size_t i = 0; i < query6.size(); i++)
{
drawcell(3, 6, 6, 9, query6[i]);
for (size_t j = 0; j < query8.size(); j++)
{
drawcell(6, 9, 3, 6, query8[j]);
if (fdfs = dfs(0))//dfs搜索是否存在满足的地图
{
cur++; break;
}
}
if (fdfs)
break;
}
if (!fdfs)
cur = 1;
break;
}
}
return;
}
bool sudo::judge(int x, int y, int k)//判断(x,y)位置放k是否可行
{
for (int i = 0; i < 6; i++)
if (table[i][y] - '0' == k)
return false;
for (int i = 0; i < 6; i++)
if (table[x][i] - '0' == k)
return false;
return true;
}
bool sudo::dfs(int cnt)//判断是否存在答案
{
static bool used[11] = { false };
if (cnt == 9)
{
return true;
}
for (int i = 1; i <= 9; i++)
{
if (!used[i])
{
used[i] = true;
if (judge(6 + cnt / 3, 6 + cnt % 3, i))
{
table[6 + cnt / 3][6 + cnt % 3] = '0' + i;
if (dfs(cnt + 1))
{
for (int k = 0; k <= 10; k++)//为了下一次使用,这里置零
used[k] = false;
return true;
}
}
used[i] = false;
}
}
return false;
}
/*
+---+---+---+---+---+---+---+---+---+ 37c
| 1 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| 2 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| 3 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| 4 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
21r +---+---+---+---+---+---+---+---+---+
| 5 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| 6 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| 7 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| 8 | 2 | 3 | 1 | 2 | 3 | 1 | 2 | 3 |
+---+---+---+---+---+---+---+---+---+
| | | | | | | | | |
+---+---+---+---+---+---+---+---+---+
A(左)、D(右)、W(上)、S(下)、1~9(数字)、R(重置)、Q(退出)、M(答案) 61c
*/
void sudo::draw()//画游戏的图
{
setcell();
clear();
int y, x;
getmaxyx(stdscr, y, x);
int cury = (y - 21) / 2, curx = (x - 37) / 2;
mvprintw(cury, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 1, curx, "| | | | | | | | | |");
mvprintw(cury + 2, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 3, curx, "| | | | | | | | | |");
mvprintw(cury + 4, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 5, curx, "| | | | | | | | | |");
mvprintw(cury + 6, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 7, curx, "| | | | | | | | | |");
mvprintw(cury + 8, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 9, curx, "| | | | | | | | | |");
mvprintw(cury + 10, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 11, curx, "| | | | | | | | | |");
mvprintw(cury + 12, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 13, curx, "| | | | | | | | | |");
mvprintw(cury + 14, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 15, curx, "| | | | | | | | | |");
mvprintw(cury + 16, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 17, curx, "| | | | | | | | | |");
mvprintw(cury + 18, curx, "+---+---+---+---+---+---+---+---+---+");
mvprintw(cury + 20, (x - 69) / 2, "A(左)、D(右)、W(上)、S(下)、1~9(数字)、C(清除)、R(重置)、Q(退出)、M(答案)");
cury = cury + 1;
curx = curx + 2;
move(cury, curx);
int initfill = random(30, 40);
remind = 81 - initfill;
for (int i = 0; i < initfill; i++)
{
move(cury, curx);
int getx = -1, gety = -1;
static default_random_engine e(unsigned(time(0)));
static uniform_int_distribution<unsigned> u(0, 8);
getx = u(e);
gety = u(e);
move(cury + 2 * gety, curx + 4 * getx);
while (inch() != ' ')
{
getx = u(e);
gety = u(e);
move(cury + 2 * gety, curx + 4 * getx);
}
curtable[gety][getx] = table[gety][getx];//根据答案地图更新当前地图
addch(table[gety][getx]);
}
move(cury, curx);
refresh();
return;
}
bool sudo::judgeans(const int& my, const int& mx, char ch)
{
char ccur = inch();
if (ccur != ' ')
return false;
int y, x;
getyx(stdscr, y, x);
int cury = y, curx = mx;
for (int i = 0; i < 9; i++)
{
move(cury, curx);
char cur = inch();
if (cur == ch)
return false;
curx += 4;
}
cury = my, curx = x;
for (int i = 0; i < 9; i++)
{
move(cury, curx);
char cur = inch();
if (cur == ch)
return false;
cury += 2;
}
cury = (y - my) / 2;
curx = (x - mx) / 4;
cury = my + cury / 3 * 3 * 2;
curx = mx + curx / 3 * 3 * 4;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
move(cury + 2 * i, curx + 4 * j);
char cur = inch();
if (cur == ch)
return false;
}
}
return true;
}
bool sudo::judgemove(const int& my, const int& mx, const int& cury, const int& curx)//判断当前位置是否越界
{
int y = (cury - my) / 2;
int x = (curx - mx) / 4;
if (x >= 0 && x <= 8 && y >= 0 && y <= 8)
return true;
return false;
}
void sudo::run()//执行
{
Resetting:
draw();
int cy, cx;
getyx(stdscr, cy, cx);
int cury = cy, curx = cx;
char ch;
while (remind)
{
ch = getch();
if (ch == 'W' || ch == 'w')
{
if (judgemove(cy, cx, cury - 2, curx))
{
cury -= 2;
move(cury, curx);
}
else
{
beep();
}
continue;
}
else if (ch == 'a' || ch == 'A')
{
if (judgemove(cy, cx, cury, curx - 4))
{
curx -= 4;
move(cury, curx);
}
else
{
beep();
}
continue;
}
else if (ch == 's' || ch == 'S')
{
if (judgemove(cy, cx, cury + 2, curx))
{
cury += 2;
move(cury, curx);
}
else
{
beep();
}
continue;
}
else if (ch == 'd' || ch == 'D')
{
if (judgemove(cy, cx, cury, curx + 4))
{
curx += 4;
move(cury, curx);
}
else
{
beep();
}
continue;
}
else if (ch >= '1' && ch <= '9')
{
if (judgeans(cy, cx, ch))
{
move(cury, curx);
addch(ch);
remind--;
}
else
{
beep();
}
move(cury, curx);
refresh();
continue;
}
else if (ch == 'c' || ch == 'C')
{
char cur = inch();
if (cur == ' ')
{
beep();
}
else
{
if (curtable[(cury - cy) / 2][(curx - cx) / 4] == ' ')
{
addch(' ');
remind++;
move(cury, curx);
}
else
{
beep();
}
//在curtable查找
}
continue;
}
else if (ch == 'r' || ch == 'R')
{
for (int ini = 0; ini <= 10; ini++)
for (int inj = 0; inj <= 10; inj++)
table[ini][inj] = curtable[ini][inj] = ' ';
goto Resetting;
}
else if (ch == 'q' || ch == 'Q')
{
endwin();
exit(0);
}
else if (ch == 'm' || ch == 'M')
{
//给出table答案
cury = cy;
curx = cx;
for (int iny = 0; iny < 9; iny++)
{
curx = cx;
for (int inx = 0; inx < 9; inx++)
{
move(cury, curx);
addch(table[(cury - cy) / 2][(curx - cx) / 4]);
curx += 4;
}
cury += 2;
}
//打印youlost
printlost();
//给出提示输入
while (1)
{
char ch = getch();
if (ch == 'r' || ch == 'R')
{
goto Resetting;
}
if (ch == 'q' || ch == 'Q')
{
endwin();
exit(0);
}
else
beep();
}
}
else
{
beep();
}
}
if (remind == 0)
{
printwin();
while (1)
{
char ch = getch();
if (ch == 'r' || ch == 'R')
{
goto Resetting;
}
if (ch == 'q' || ch == 'Q')
{
endwin();
exit(0);
}
else
beep();
}
}
beep();
return;
}
/*youwin
+ + ++ + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + + + + + + + + + + +
+ ++ ++ + + + + + +
按Q退出,按R重新开始,请输入:
*/
/*youlost
+ + ++ + + + ++ ++ + + + +
+ + + + + + + + + + + +
+ + + + + + + + ++ + +
+ + + + + + + + + +
+ ++ ++ + + + ++ ++ + +
按Q退出,按R重新开始,请输入:
*/
void sudo::printwin()//打印youwin
{
int y, x;
getmaxyx(stdscr, y, x);
int cury = (y - 21) / 2, curx = (x - 37) / 2;
mvprintw(cury + 22, (x - 60) / 2, "+ + ++ + + + + + + + +");
mvprintw(cury + 23, (x - 60) / 2, " + + + + + + + + + + + +");
mvprintw(cury + 24, (x - 60) / 2, " + + + + + + + + + + + + +");
mvprintw(cury + 25, (x - 60) / 2, " + + + + + + + + + + + + ");
mvprintw(cury + 26, (x - 60) / 2, " + ++ ++ + + + + + +");
mvprintw(cury + 28, (x - 30) / 2, "按Q退出,按R重新开始,请输入:");
return;
}
void sudo::printlost()//打印youlost
{
int y, x;
getmaxyx(stdscr, y, x);
int cury = (y - 21) / 2, curx = (x - 37) / 2;
mvprintw(cury + 22, (x - 60) / 2, "+ + ++ + + + ++ ++ + + + +");
mvprintw(cury + 23, (x - 60) / 2, " + + + + + + + + + + + +");
mvprintw(cury + 24, (x - 60) / 2, " + + + + + + + + ++ + +");
mvprintw(cury + 25, (x - 60) / 2, " + + + + + + + + + + ");
mvprintw(cury + 26, (x - 60) / 2, " + ++ ++ + + + ++ ++ + +");
mvprintw(cury + 28, (x - 30) / 2, "按Q退出,按R重新开始,请输入:");
return;
}
sudo::sudo()
{
initable = new char* [362881];
for (int i = 0; i <= 362880; i++)
initable[i] = new char[10];
table = new char* [11];
for (int i = 0; i <= 10; i++)
table[i] = new char[11];
curtable = new char* [11];
for (int i = 0; i <= 10; i++)
curtable[i] = new char[11];
for (int i = 0; i <= 10; i++)
for (int j = 0; j <= 10; j++)
table[i][j] = curtable[i][j] = ' ';
numbers = 0;
remind = 0;
}
sudo::~sudo()
{
for (int i = 0; i <= 362880; i++)
delete[] initable[i];
delete[] initable;
for (int i = 0; i <= 10; i++)
delete[] table[i];
delete[] table;
for (int i = 0; i <= 10; i++)
delete[] curtable[i];
delete[] curtable;
initable = NULL;
remind = 0;
}