前言
這一段時間學了不少東西,想找個項目歷練一下,就去牛客上翻了翻,看到這個我小時候經常玩的遊戲,就想開發一下試試。因爲第一次做項目,不知道如何做,就去牛客此項目下的評論區看了下別人的作品,發現算法有錯,不能正常玩,決定自己開發一個能玩的遊戲。
遊戲介紹
數獨是源自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;
}