第一篇:數據結構課程設計-五子棋
姓 名: 劉旭
學 院: 計算機與通信學院
班 級: 通信工程101班
指導老師: 文志誠
目錄
一、需求分析..................................................................................................................................3 1.1 開發背景....................................................................................................................................3 2.2 功能簡介....................................................................................................................................3
二、系統設計..................................................................................................................................4 2.1 函數一覽....................................................................................................................................4 2.2 “封面”的設計........................................................................................................................4 2.3 二維數組與控制臺....................................................................................................................5 2.4 鍵盤操作....................................................................................................................................6 2.5判定.............................................................................................................................................7 2.6 悔棋的實現................................................................................................................................8
三、調試運行..................................................................................................................................9 3.1 進入界面....................................................................................................................................9 3.2 棋盤的初始狀態......................................................................................................................10 3.3 激戰中……..............................................................................................................................10 3.4 游戲結束..................................................................................................................................11
四、解決問題的關鍵....................................................................................................................11
五、課設總結................................................................................................................................11
六、附錄........................................................................................................................................12 6.1 畫圖代碼..................................................................................................錯誤!未定義書簽。6.2 初始化......................................................................................................錯誤!未定義書簽。6.3 Play函數..................................................................................................錯誤!未定義書簽。
一、需求分析
1.1 開發背景
學習了數據結構該門課程,對于枯燥無味的理論知識,我們是否能夠通過所學的知識在課程設計中做出有趣味東西,然后讓我們對于數據結構更加的感興趣呢?于是我和我的室友陳明建開始醞釀著寫些什么東西。上個學期就已經寫了通訊錄那之類的鏈式結構,這次我們決心有所改變,我們學習了棧、隊列、樹、圖,字典樹有人選了,我們就來寫一個基于圖的小程序,五子棋,對,圖的簡單應用,于是我們開始著手來寫這個小小的程序,祝我們好運!
2.2 功能簡介
既然是五子棋,我們要做的是時時刻刻的將整個圖(以下稱為棋局)的狀態呈現出來,那么界面就是必不可少的。MFC不會?沒關系,我們就用基于控制臺的字符輸出來構建這個棋局吧,當然這只是第一步,詳細如下: 1擁有一個良好的進入界面,以及必要的選項; ○2擁有一個二維的數組來記錄和更新實時的狀態,并且能夠有一種方法在DOS界面下繪制○出整個棋局的實時狀態(包括棋盤和棋子);
3能夠通過鍵盤上的按鍵完成所選位置的移動和選定操作; ○4能夠在每一次的走棋后判定是否游戲結束(棋盤走滿或者是一方勝出); ○5能夠完成悔棋的功能,并保證這之間的棋局繪圖能夠與二維數組數據同步,做到真正意○義上的悔棋。
二、詳細設計
2.1 函數一覽
2.2 “封面”的設計
首先還是講些題外話,該程序由于與控制臺有密切的關系,于是在代碼中使用了不少 conio.h 中的函數,當然在顯示時又使用了windows.h 中的 Sleep()函數,正是有了這些函數的使用,程序才得以順利完成,尤其是后面頻繁使用的gotoxy()函數。
進入正題,由于是一個小的程序,因此將每一個功能分成一個一個的函數,這樣將在以后的修改和完成進度上都有很大的幫助。由上面的函數一覽可以知道這個“封面”就是在Logo()函數里面實現的,函數實現過程中使用了Sleep()函數,使之有動態效果:
void Logo(){
char Wel[30]= { “Made By Lyush&& Mirs Chen” };
printf(“ttt
歡迎試用五子棋系統n”);
printf(“tt
”);
for(int i= 0;i< strlen(Wel);++i)
{
putchar(Wel[i]);
Sleep(200);// 可使字符一個一個的輸出
}
putchar(10);// 換行對應的 ASCII 碼值為十進制的 10 }
2.3 二維數組與控制臺
二維數組是用來使得整個棋盤的信息全部記錄下來,因此在結構體中二維數組的聲明是最關鍵的。
struct {
int Status[MAX/2+2][MAX/2+2];
int MINBOX;
int Step;
char Graph[3][3];
char *FillGraph[9];
Sta Stack;} ChessBoard;
聲明全局變量是為了使得各函數能夠更方便地使用到這個結構體,現假設某點的坐標為(1, 1),那么如何在屏幕上打印這個點呢?這就利用到了ChangeCoordinates()與gotoxy()函數,前者使坐標進行轉換,后者讓光標走到所指的那個點,其實主要還是因為類似“┣、╋、●、○”在橫向上所占都是兩個英文字母的距離,因此在控制臺上反映的就是和數組下標倍數關系了。部分代碼如下:
HANDLE hConsole= GetStdHandle(STD_OUTPUT_HANDLE);
void ChangeCoordinates(int _X, int _Y, int *X, int *Y){
*X=(_X-1)* 2;
*Y=(_Y-1)* 4;}
void gotoxy(int x, int y)//這是光標的函數 {
COORD coord;
coord.Y= x;
// 在實際的應用過程中發現交換x與y的賦值
coord.X= y;
// 更好理解,即橫行位x,縱行為y。
SetConsoleCursorPosition(hConsole, coord);
}
2.4 鍵盤操作
在剛開始寫這個五子棋的時候是以坐標來確定玩家的每一步棋,但后來發現這樣操作性實在是差,鍵盤操作是更好的選擇。這里又要用到一個函數 getch(),其作用是無回顯的接受從鍵盤輸入的字符,讓屏幕不會出現你輸入的字符且等待著按回車確定…… 有了這個寶貝函數,馬上得到 “↑” 對應的ASCII碼為-32和72 兩個連著的數值,依次可得其他對應的ASCII碼。后面在使玩家一和玩家二分離操作,玩家一則是利用 W、S、A、D + space來操作,玩家二則是 上下左右+ enter。配合ChangeCoordinates()與gotoxy()函數,完成對走棋的控制。部分代碼如下:
if(Opreat[0]== 13&& Ply== 2|| Opreat[0]== 32&& Ply== 1){ if(ChessBoard.Status[Move_X][Move_Y]== 0)
{
int TTop= ++ChessBoard.Stack.Top;ChessBoard.Status[Move_X][Move_Y]= Ply;ChessBoard.Stack.Record[TTop][0]= Move_X;ChessBoard.Stack.Record[TTop][1]= Move_Y;printf(“%s”, Graph);return true;// 該次走棋操作有效
} else { … } } if(Opreat[0]==-32&& Opreat[1]== 72|| Opreat[0]== 'w'|| Opreat[0]== 'W'){// 凡是接受了“上操作”,則Move_X的值減一,if(Currect(Move_X-1, Move_Y))
{
Move_X-= 1;
} } else if(…){ … }
// 這是接下來的轉換操作
ChangeCoordinates(Move_X, Move_Y, &Temp_X, &Temp_Y);Gotoxy(Temp_X, Temp_Y);
2.5判定
對于每次走棋后,首先應該做的就是判定一否有五個棋子已經連成一線,也是一個簡單的搜索過程,由于每次走的點不一定是最外部的點,因此從每次走的點的兩頭同時搜索,當遇到兩端同時結束時,搜索結束。當滿足五子時游戲結束。當然,當棋盤被走滿時,游戲亦結束。代碼如下: bool Legal(int Point){
if(Point< 1|| Point> MAX/ 2+ 1)
return false;
else
return true;}
//搜索45度角是否為滿足ChessBoard.MINBOX 以X正軸為參考軸
if(!Flag){ Count= 1;for(int i1= X-1, j1= Y+ 1, i2= X+ 1, j2= Y-1;Legal(i1)&& Legal(j1)|| Legal(i2)&& Legal(j2);i1--, j1++, i2++, j2--){
int LastCount= Count;
if(Legal(i1)&& Legal(j1)&& ChessBoard.Status[i1][j1]== Ply)
{
Count++;
}
if(Legal(i2)&& Legal(j2)&& ChessBoard.Status[i2][j2]== Ply)
{
Count++;
}
if(LastCount== Count)
break;
if(Count== ChessBoard.MINBOX){
Flag= 1;
return true;
} } }
2.6 悔棋的實現
雖說下棋悔棋是一種不道義的行為,但是如果雙方約定好了,未嘗不可。在沒寫悔棋之前,只是記錄了“上一次”的位置,聲明了Last_X,Last_Y;當然既然要求悔棋,那么直接調用棧頂元素,即可定位上次走棋的位置。那么悔棋呢,取出“上一次”的位置,判定位置(不同的位置對應不同的填充圖形類型)在二維數組中撤銷走棋時所賦予的 Ply 值(玩家一走時,其值為1,玩家二走時,其值為2),重新將 ChessBoard.Status[ Last_X ][ Last_Y ] 賦為0。代碼如下:
int GetFillType(int X, int Y){
if(X== 1)
{
if(Y== 1)
return 0;
else if(Y== 16)
return 2;
else
return 1;
}
else if(X== 16)
{
if(Y== 1)
return 6;
else if(Y== 16)
return 8;
else
return 7;
}
else
{
if(Y== 1)
return 3;
else if(Y== 16)
return 5;
else
return 4;
} }
bool Retract(int *X, int *Y){
int Temp_X, Temp_Y, TTop, FillType;
if(!StackEmpty())
{
TTop= ChessBoard.Stack.Top--;
*X= ChessBoard.Stack.Record[TTop][0];
*Y= ChessBoard.Stack.Record[TTop][1];
ChessBoard.Status[*X][*Y]= 0;// 將該點置為真正意義上的空點
FillType= GetFillType(*X, *Y);
ChangeCoordinates(*X, *Y, &Temp_X, &Temp_Y);
Gotoxy(Temp_X, Temp_Y);
printf(“%s”, ChessBoard.FillGraph[FillType]);
return true;
}
else
{
Gotoxy(9, 65);
printf(“您已不能悔棋”);
Sleep(300);
Gotoxy(9, 65);
printf(“
”);
return false;
} }
三、調試運行
3.1 進入界面
3.2 棋盤的初始狀態
3.3 激戰中……
3.4 游戲結束
四、解決問題的關鍵
這個五子棋的程序并沒有什么復雜的算法,只是利用了簡單的圖知識和一個棧的應用,在這里主要的關鍵問題就是如何將程序有條理的寫下來,有一個好的邏輯思維。將程序分成了多個功能函數,盡量的讓一個函數的功能單一,只是在內部調用了其他的函數以輔助改函數功能的實現,比如判定坐標是否越界,坐標是否合法,悔棋的點的位置狀態…… 這樣便能做到各個擊破,程序的形成也就變得暢通許多了。
五、課設總結
剛開始寫這個程序,認為一定要用到 graphics.h, 無奈電腦TC不兼容,因此只好強行來畫這個界面了,使用輸入法里面的制表符,效果還不錯,通過一長串的if … else … 最好還是畫出來了,這個時候覺得控制臺的簡單圖形還是能夠畫出來的,并且可以盡量去美化它的界面。后面的附錄中將給出畫棋盤和棋子的源代碼。在程序設計的過程中,尤其是為源程序加上悔棋的功能,這期間總是有許多意想不到的錯誤,比如加上后,有時走了5個連子棋,但是程序并沒有判定輸贏,而是可以繼續走、有時沒有五個卻已經結束了,光標沒有復位,悔棋后,玩家的走棋順序沒有跟著改變……通過后來的一步步修改終于使得這些問題都一一解決了,比如說對 Prompt(提示)函數引進了返回值,判斷該次操作是否成功,如果下了棋則為 true,如果是悔棋就是 false 了,這樣便使得后面的操作更規范了和統一了。
六、附錄
#include
HANDLE hConsole= GetStdHandle(STD_OUTPUT_HANDLE);
void HideCursor(){ CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);}
typedef struct {
int Record[260][2];
int Base;
int Top;} Sta;
struct {
int Status[MAX/2+2][MAX/2+2];
int MINBOX;
int Step;
char Graph[3][3];
char *FillGraph[9];
Sta Stack;
} ChessBoard;
void Gotoxy(int x, int y)//這是光標的函數 {
COORD coord;
coord.Y= x;
coord.X= y;
SetConsoleCursorPosition(hConsole, coord);
}
void Logo(){
char Wel[30]= { “Made By Lyush&& Mirs Chen” };
printf(“ttt
歡迎試用五子棋系統n”);
printf(“tt
”);
for(int i= 0;i< strlen(Wel);++i)
{
putchar(Wel[i]);
Sleep(200);
}
putchar(10);}
int Login(){
int Mode, Skip= 0;
char Request;
if(!Skip)
{
printf(“nn在這兒你能DIY(Do it youself!)你的棋子,每個棋子接受一個漢字”);
printf(“ Y Orz Nn”);
scanf(“%c”, &Request);
if(Request== 'Y'|| Request== 'y')
{
printf(“玩家一的 DIY 棋子-->”);
scanf(“%s”, ChessBoard.Graph[1]);
ChessBoard.Graph[1][2]= ' 主站蜘蛛池模板: 97在线视频人妻无码| 18禁美女裸体网站无遮挡| 久久久久久好爽爽久久| 国产三级久久久精品麻豆三级| 日出水了特别黄的视频| 精产国品一二三产区m553麻豆| av天堂精品久久久久2| 产后漂亮奶水人妻无码| 2021国产精品国产精华| 亚洲成年看片在线观看| 无遮挡又爽又刺激的视频| 欧美成人精品三级网站下载| 99精品久久99久久久久胖女人| 天堂www中文在线资源| 永久免费不卡在线观看黄网站| 岛国av无码免费无禁网站麦芽| 亚洲精品tv久久久久久久久久| 免费人妻无码不卡中文字幕系| 国产国拍亚洲精品永久69| 国产做a爱免费视频在线观看| 日韩伦人妻无码| 公和我做好爽添厨房| 国产精品无码人妻一区二区在线| 国产成人精品一区二三区在线观看| 女人被爽到呻吟gif动态图视看| 亚洲伊人久久精品酒店| 成年无码av片在线蜜芽| 亚洲精品国产一区二区三| 最近日本中文字幕免费完整| 人妻熟女欲求不满在线| 国产香蕉国产精品偷在线| 国产国拍亚洲精品永久软件| 久久的爱久久久久的快乐| 亚洲中文字幕aⅴ无码天堂| 久久久久夜夜夜综合国产| 夜精品a片一区二区三区无码白浆| 57pao成人国产永久免费视频| 99久9在线视频 | 传媒| 少妇无码av无码专线区大牛影院| 精品视频在线观自拍自拍| 国产精品亚洲综合色区|