C語言實現(xiàn)五子棋人人對戰(zhàn)
利用簡單的c語言基礎實現(xiàn)最簡單的功能,界面比較丑陋主要是剛學完c的一個小實踐,未使用MFC所以界面沒有很好看 ,主要目的加強對c語言的理解與運用,同時增加自己的代碼量。
首先要學一些頭文件可以看我的博客前面的文章
要用到到的頭文件stdio.h stdlib.h windows.h time.h conio.h
思路就是
1.畫個棋盤,使用數(shù)組來代替初始化出*
2.使用循環(huán)使雙方輪流下棋,使用數(shù)組存放棋子的位置
3.判斷是否有一方獲勝
首先打印棋盤
#include<stdio.h> #include<windows.h> #include<conio.h> #include<stdlib.h> char qipan[16][16]; //函數(shù)聲明 void initQipan();//將*存入16*16的二維數(shù)組中 void printQipan();//將二維數(shù)組打印出來 void initQipan() { int i,j; for(i = 0;i < 16 ;i++) for(j = 0;j <16 ;j++) qipan[i][j] = '*'; } void printQipan() { int i,j; for(i = 0;i < 16 ;i++) { for(j = 0;j <16 ;j++) printf("%c",qipan[i][j]); printf("\n"); } } int main() { initQipan(); printQipan(); }
打印出來效果圖
這里面我發(fā)現(xiàn)一個算是c語言的小陷阱
void printQipan() { int i,j; for(i = 0;i < 16 ;i++) { for(j = 0;j <16 ;j++) printf("%c",qipan[i][j]); printf("\n"); } }
這段代碼中內層for循環(huán)后跟著兩個語句但是按正常想法應該兩條語句都應隨著內層循環(huán)而循環(huán)也就是打出來的應該是這樣
打印出來這樣的代碼是
int i,j; for(i = 0;i < 16 ;i++) { for(j = 0;j <16 ;j++) { printf("%c",qipan[i][j]); printf("\n"); } }
但是顯然他們的效果不等價
這樣其實是因為如果內層沒有寫出{}就會默認將第一條指令給內層,其余所有指令給外層
可以看下面的代碼
int i,j; for(i = 0;i < 16 ;i++) { for(j = 0;j <16 ;j++) printf("%c",qipan[i][j]); printf(","); printf("\n"); } }
這樣很顯然得出結論
在這樣結構的雙重for循環(huán)中
for() { for() 語句1 語句2 語句3 ... }
只有第一條語句屬于內存循環(huán),寫成這樣更加明了一些
for() { for() 語句1 語句2 語句3 ... }
下面實現(xiàn)雙方輪流下棋
/*************************************頭文件********************************************/ #include<stdio.h> #include<windows.h> #include<conio.h> #include<stdlib.h> /************************************全局變量********************************************/ char qipan[16][16]; int x,y; /************************************函數(shù)聲明********************************************/ void initQipan();//將*存入16*16的二維數(shù)組中 void printQipan();//將二維數(shù)組打印出來 void starGame();//開始游戲 /************************************自定義函數(shù)******************************************/ void initQipan() { int i,j; for(i = 0;i < 16 ;i++) for(j = 0;j <16 ;j++) qipan[i][j] = '*'; } void printQipan() { int i,j; for(i = 0;i < 16 ;i++) { for(j = 0;j <16 ;j++) printf("%c",qipan[i][j]); printf("\n"); } } void starGame() { initQipan(); printQipan(); while(1) { printf("請白方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y); qipan[x][y]='W'; system("cls"); printQipan(); printf("請黑方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y); qipan[x][y]='B'; system("cls"); printQipan(); } } /*****************************************主函數(shù)****************************************/ int main() { starGame(); }
現(xiàn)在可以實現(xiàn)雙方輪流下棋,接下來就是要實現(xiàn)系統(tǒng)去判定是否有人獲勝
/*********************************************************************頭文件*************************************************************************************/ #include<stdio.h> #include<windows.h> #include<conio.h> #include<stdlib.h> /********************************************************************全局變量************************************************************************************/ char qipan[16][16]; int x,y; /********************************************************************函數(shù)聲明************************************************************************************/ void initQipan();//將*存入16*16的二維數(shù)組中 void printQipan();//將二維數(shù)組打印出來 void starGame();//開始游戲 int panduan(int x,int y);//判斷是否有人獲勝 void win(int winner);//有人獲勝后顯示那方勝利 /********************************************************************自定義函數(shù)**********************************************************************************/ void initQipan() { int i,j; for(i = 0;i < 16 ;i++) for(j = 0;j <16 ;j++) qipan[i][j] = '*'; } void printQipan() { int i,j; for(i = 0;i < 16 ;i++) { for(j = 0;j <16 ;j++) printf("%c",qipan[i][j]); printf("\n"); } } void starGame() { int temp; initQipan(); printQipan(); while(1) { printf("請白方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y); qipan[x][y]='W'; system("cls"); printQipan(); temp = panduan(x,y); if(temp==1) { printf("白方獲勝"); system("pause"); } printf("請黑方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y); qipan[x][y]='B'; system("cls"); printQipan(); temp = panduan(x,y); if(temp==2) { printf("黑方獲勝"); system("pause"); } } } int panduan(int x,int y) { char temp;//保存棋子的顏色 int winner;//1代表白方,2代表黑方 int i;//距離落子位置水平方向的差 int j;//距離落子位置豎直方向的差 int count;//記下有多少個連續(xù)的棋子 count = 1; i = 1; j = 1; winner = 0; temp = qipan[x][y]; //***************************************************************************水平方向************************************************************************** //水平左邊 while(temp = qipan[x-i][y]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { i++; count++; if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //水平右邊 i = 1;//因為要重新從一格開始移動,初始化i變量 while(temp = qipan[x+i][y]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { i++; count++;//此時count是接著水平左邊繼續(xù)累加 if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //**************************************************************************豎直方向*************************************************************************** //豎直上方 i = 1;//初始化變量 count = 1;//初始化變量 while(temp = qipan[x][y+j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { j++; count++; if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //豎直下方 i = 1;//因為要重新從一格開始移動,初始化i變量 while(temp = qipan[x][y-j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { j++; count++;//此時count是接著水平左邊繼續(xù)累加 if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //**************************************************************************從左向右傾斜*********************************************************************** //左上方 i = 1;//初始化變量 count = 1;//初始化變量 while(temp = qipan[x-i][y-j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { i++; j++; count++; if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //右下方 i = 1;//因為要重新從一格開始移動,初始化i變量 while(temp = qipan[x+i][y+j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { i++; j++; count++;//此時count是接著水平左邊繼續(xù)累加 if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //**************************************************************************從右向左傾斜*********************************************************************** //右上方 i = 1;//初始化變量 count = 1;//初始化變量 while(temp = qipan[x-i][y+j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { i++; j++; count++; if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } //左下方 i = 1;//因為要重新從一格開始移動,初始化i變量 while(temp = qipan[x+i][y-j]&&x >= 0&&x <= 15&&y >= 0&&y <= 15&&count < 5) { i++; j++; count++;//此時count是接著水平左邊繼續(xù)累加 if(count==5)//如果連成五子出現(xiàn)勝利的一方,否則繼續(xù)判斷 { if(temp=='W') winner = 1; else winner = 2; } } return winner; } /*******************************************************************主函數(shù)**************************************************************************************/ int main() { starGame(); return 0; }
此時有一個問題就是程序會卡死如圖
在寫程序時出現(xiàn)這種錯誤可能的原因是:
①除以零
②數(shù)組越界:int a[3]; a[10000000]=10;
③指針越界:int * p; p=(int *)malloc(5 * sizeof(int)); *(p+1000000)=10;
④使用已經(jīng)釋放的空間:int * p; p=(int *)malloc(5 * sizeof(int));free(p); *p=10;
⑤數(shù)組開得太大,超出了棧的范圍,造成棧溢出:int a[100000000]
ok發(fā)現(xiàn)問題是在如圖位置沒有初始化這幾個變量現(xiàn)在已經(jīng)將上面的代碼修正了
下面來看最后優(yōu)化完的代碼
/***************************************頭文件******************************************/ #include<stdio.h> #include<windows.h> #include<conio.h> #include<stdlib.h> /****************************************宏*********************************************/ #define N 16 //可以更改棋盤大小 /***************************************全局變量*****************************************/ char qipan[N][N];//全局變量,整個文件的都可以用 int x,y;//代表的是棋盤(數(shù)組)下標為x的行 和 下標為y列的一個交點 /***************************************函數(shù)聲明*****************************************/ void initQipan();//棋盤的初始化 void printQipan();//打印棋盤 void Pos(int x, int y);//設置光標位置 void startGame();//游戲開始 int panduan(int x,int y);//判斷是否有人連成五子 int showWhoWin();//輸出誰贏了 void whitePlay();//白方下子 void blackPlay();//黑方下子 void printShuzi();//打印數(shù)字模板 /*****************************************自定義函數(shù)*************************************/ void Pos(int x, int y)//設置光標位置,從哪里開始輸出 { COORD pos;//表示一個字符在控制臺屏幕上的坐標,左上角(0,0) HANDLE hOutput; pos.X = x; pos.Y = y; hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//返回標準的輸入、輸出或錯誤的設備的句柄,也就是獲得輸入、輸出/錯誤的屏幕緩沖區(qū)的句柄 SetConsoleCursorPosition(hOutput, pos); } void printShuzi() { int i; Pos(2,0); for(i=0;i<N;i++) printf("%2d",i); for(i=0;i<16;i++) { Pos(0,1+i); printf("%2d",i); } } void initQipan() { int i,j; for(i=0;i<N;i++) for(j=0;j<N;j++) qipan[i][j]='*'; } void printQipan() { int i,j; printShuzi(); for(i=0;i<N;i++) { Pos(2,1+i);//自動換行的輸出的功能,代替printf("\n"); for(j=0;j<N;j++) printf(" %c",qipan[i][j]); } } int panduan(int x,int y) { char temp;//保存下棋方的顏色,w b int count=1;//統(tǒng)計個數(shù),針對的同一個線(水平線) int i=1;//走一格 int j=1;//和i同時用來代表走斜的 int whoWin=0;//1代表白方,2代表黑方 temp=qipan[x][y]; //水平的左邊 while(temp==qipan[x][y-i]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //水平的右邊 i=1; while(temp==qipan[x][y+i]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //解決垂直的方向 //垂直上方 i=1; count=1;//清理掉之前的數(shù)據(jù) while(temp==qipan[x-i][y]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //垂直下方 i=1; while(temp==qipan[x+i][y]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //解決左上的斜線 上方 i=1; j=1; count=1; while(temp==qipan[x-i][y-j]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; j++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //解決左上的斜線 下方 i=1; j=1; while(temp==qipan[x+i][y+j]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; j++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //解決右上的斜線 上方 i=1; j=1; count=1; while(temp==qipan[x-i][y+j]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; j++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } //解決右上的斜線 下方 i=1; j=1; while(temp==qipan[x+i][y-j]&&x>=0&&x<N&&y>=0&&y<N&&count<5) { i++; j++; count++; if(count==5)//首先count是5才能來判斷誰贏了 { if(temp=='W') whoWin=1; else whoWin=2; } } return whoWin; } int showWhoWin() { int overLeap=0;//1代表結束 int leap;//用來接收誰贏了 leap=panduan(x,y); if(leap==1) { overLeap=1; system("cls"); printQipan(); printf("\n白方勝利\n"); system("pause"); } if(leap==2) { overLeap=1; system("cls"); printQipan(); printf("\n黑方勝利\n"); system("pause"); } return overLeap; } void whitePlay() { printf("\n請白方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y);//坐標的值 while(1)//解決一直下錯子的問題 { if(qipan[x][y]=='*')//下子的地方?jīng)]有其他子 { qipan[x][y]='W'; //解決while(1) break; } else { printf("您下子錯誤\n"); printf("請白方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y);//坐標的值 } } printQipan(); } void blackPlay() { printQipan(); printf("\n請黑方落子,按下行與列的坐標:"); scanf("%d%d",&x,&y);//坐標的值 while(1)//解決一直下錯子的問題 { if(qipan[x][y]=='*')//下子的地方?jīng)]有其他子 { qipan[x][y]='B'; //解決while(1) break; } else { printf("您下子錯誤\n"); printf("請黑方落子,按下行與列的坐標:"); } scanf("%d%d",&x,&y);//坐標的值 } printQipan(); } void startGame() { initQipan(); printQipan(); while(1) { whitePlay(); if(showWhoWin()==1)//system("pause"); break; system("cls");//清理屏幕,是屏幕上的字不重復 blackPlay(); if(showWhoWin()==1)//system("pause"); break; system("cls"); printQipan(); } printf("您是否重新游戲:y or n"); if(getch()=='n') { system("cls"); printf("游戲結束\n"); exit(0);//因為程序終止 } if(getch()=='y') { system("cls"); startGame(); } } /*********************************************主函數(shù)************************************/ int main() { startGame(); return 0; }
下面測試一下功能
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
淺析ORB、SURF、SIFT特征點提取方法以及ICP匹配方法
這篇文章主要為大家介紹了常用的特征點提取方法(ORB、SURF、SIFT)和ICP匹配方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2021-12-12