C語言實現(xiàn)五子棋游戲,編譯運行后如圖
上下左右移動光標(biāo)位置,空格為下子,黑白交替,可以自娛自樂~
運行效果如下:
編譯器Vc6.0,親自無問題
代碼如下:
#include <stdlib.h> #include <stdio.h> #include <conio.h> #include <string.h> #define MAXIMUS 15 //定義棋盤大小 int p[MAXIMUS][MAXIMUS];//存儲對局信息 char buff[MAXIMUS*2+1][MAXIMUS*4+3];//輸出緩沖器 int Cx,Cy;//當(dāng)前光標(biāo)位置 int Now;//當(dāng)前走子的玩家,1代表黑,2代表白 int wl,wp;//當(dāng)前寫入緩沖器的列數(shù)和行數(shù)位置 char* showText;//在棋盤中央顯示的文字信息 int count;//回合數(shù) char* Copy(char* strDest,const char* strSrc)//修改過的字符串復(fù)制函數(shù),會忽略末端的\0 { char* strDestCopy = strDest; while (*strSrc!='\0') { *strDest++=*strSrc++; } return strDestCopy; } void Initialize()//初始化一個對局函數(shù) { int i,j;//循環(huán)變量 showText="";//重置顯示信息 count=0;//回合數(shù)歸零 for(i=0;i<MAXIMUS;i++)//重置對局?jǐn)?shù)據(jù) { for(j=0;j<MAXIMUS;j++) { p[i][j]=0; } } Cx=Cy=MAXIMUS/2;//重置光標(biāo)到中央 Now=1;//重置當(dāng)前為黑方 } char* getStyle(int i,int j)//獲得棋盤中指定坐標(biāo)交點位置的字符,通過制表符拼成棋盤 { if(p[i][j]==1)//1為黑子 return "●"; else if(p[i][j]==2)//2為白子 return "○"; else if(i==0&&j==0)//以下為邊緣棋盤樣式 return "┏"; else if(i==MAXIMUS-1&&j==0) return "┓"; else if(i==MAXIMUS-1&&j==MAXIMUS-1) return "┛"; else if(i==0&&j==MAXIMUS-1) return "┗"; else if(i==0) return "┠"; else if(i==MAXIMUS-1) return "┨"; else if(j==0) return "┯"; else if(j==MAXIMUS-1) return "┷"; return "┼";//中間的空位 } char* getCurse(int i,int j) {//獲得指定坐標(biāo)交點位置左上格的樣式,通過制表符來模擬光標(biāo)的顯示 if(i==Cx) { if(j==Cy) return "┏"; else if (j==Cy+1) return "┗"; } else if(i==Cx+1) { if(j==Cy) return "┓"; else if (j==Cy+1) return "┛"; } return " ";//如果不在光標(biāo)附近則為空 } void write(char* c)//向緩沖器寫入字符串 { Copy(buff[wl]+wp,c); wp+=strlen(c); } void ln()//緩沖器寫入位置提行 { wl+=1; wp=0; } void Display()//將緩沖器內(nèi)容輸出到屏幕 { int i,l=strlen(showText);//循環(huán)變量,中間文字信息的長度 int Offset=MAXIMUS*2+2-l/2;//算出中間文字信息居中顯示所在的橫坐標(biāo)位置 if(Offset%2==1)//如果位置為奇數(shù),則移動到偶數(shù),避免混亂 { Offset--; } Copy(buff[MAXIMUS]+Offset,showText);//講中間文字信息復(fù)制到緩沖器 if(l%2==1)//如果中間文字長度為半角奇數(shù),則補上空格,避免混亂 { *(buff[MAXIMUS]+Offset+l)=0x20; } system("cls");//清理屏幕,準(zhǔn)備寫入 for(i=0;i<MAXIMUS*2+1;i++){//循環(huán)寫入每一行 printf("%s",buff[i]); if(i<MAXIMUS*2)//寫入完每一行需要換行 printf("\n"); } } void Print()//將整個棋盤算出并儲存到緩沖器,然后調(diào)用Display函數(shù)顯示出來 { int i,j;//循環(huán)變量 wl=0; wp=0; for(j=0;j<=MAXIMUS;j++)//寫入出交點左上角的字符,因為需要打印棋盤右下角,所以很以橫縱各多一次循環(huán) { for(i=0;i<=MAXIMUS;i++) { write(getCurse(i,j));//寫入左上角字符 if(j==0||j==MAXIMUS)//如果是棋上下盤邊緣則沒有連接的豎線,用空格填充位置 { if(i!=MAXIMUS) write(" "); } else//如果在棋盤中間則用豎線承接上下 { if(i==0||i==MAXIMUS-1)//左右邊緣的豎線更粗 write("┃"); else if(i!=MAXIMUS)//中間的豎線 write("│"); } } if(j==MAXIMUS)//如果是最后一次循環(huán),則只需要處理邊側(cè)字符,交點要少一排 { break; } ln();//提行開始打印交點內(nèi)容 write(" ");//用空位補齊位置 for(i=0;i<MAXIMUS;i++)//按橫坐標(biāo)循環(huán)正常的次數(shù) { write(getStyle(i,j));//寫入交點字符 if(i!=MAXIMUS-1)//如果不在最右側(cè)則補充一個橫線承接左右 { if(j==0||j==MAXIMUS-1) { write("━");//上下邊緣的橫線更粗 } else { write("—");//中間的橫線 } } } ln();//寫完一行后提行 } Display();//將緩沖器內(nèi)容輸出到屏幕 } int Put(){//在當(dāng)前光標(biāo)位置走子,如果非空,則返回0表示失敗 if(p[Cx][Cy]==0) { p[Cx][Cy]=Now;//改變該位置數(shù)據(jù) return 1;//返回1表示成功 } else { return 0; } } int Check()//勝負(fù)檢查,即判斷當(dāng)前走子位置有沒有造成五連珠的情況 { int w=1,x=1,y=1,z=1,i;//累計橫豎正斜反邪四個方向的連續(xù)相同棋子數(shù)目 for(i=1;i<5;i++)if(Cy+i<MAXIMUS&&p[Cx][Cy+i]==Now)w++;else break;//向下檢查 for(i=1;i<5;i++)if(Cy-i>0&&p[Cx][Cy-i]==Now)w++;else break;//向上檢查 if(w>=5)return Now;//若果達到5個則判斷當(dāng)前走子玩家為贏家 for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&p[Cx+i][Cy]==Now)x++;else break;//向右檢查 for(i=1;i<5;i++)if(Cx-i>0&&p[Cx-i][Cy]==Now)x++;else break;//向左檢查 if(x>=5)return Now;//若果達到5個則判斷當(dāng)前走子玩家為贏家 for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy+i<MAXIMUS&&p[Cx+i][Cy+i]==Now)y++;else break;//向右下檢查 for(i=1;i<5;i++)if(Cx-i>0&&Cy-i>0&&p[Cx-i][Cy-i]==Now)y++;else break;//向左上檢查 if(y>=5)return Now;//若果達到5個則判斷當(dāng)前走子玩家為贏家 for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy-i>0&&p[Cx+i][Cy-i]==Now)z++;else break;//向右上檢查 for(i=1;i<5;i++)if(Cx-i>0&&Cy+i<MAXIMUS&&p[Cx-i][Cy+i]==Now)z++;else break;//向左下檢查 if(z>=5)return Now;//若果達到5個則判斷當(dāng)前走子玩家為贏家 return 0;//若沒有檢查到五連珠,則返回0表示還沒有玩家達成勝利 } int RunGame()//進行整個對局,返回贏家信息(雖然有用上) { int input;//輸入變量 int victor;//贏家信息 Initialize();//初始化對局 while(1){//開始無限回合的死循環(huán),直到出現(xiàn)勝利跳出 Print();//打印棋盤 input=getch();//等待鍵盤按下一個字符 if(input==27)//如果是ESC則退出程序 { exit(0); } else if(input==0x20)//如果是空格則開始走子 { if(Put())//如果走子成功則判斷勝負(fù) { victor=Check(); Now=3-Now;//輪換當(dāng)前走子玩家 count++; if(victor==1)//如果黑方達到勝利,顯示提示文字并等待一次按鍵,返回勝利信息 { showText="黑方獲得了勝利!"; Print(); if(getch()==0xE0) { getch(); } return Now; } else if(victor==2)//如果白方達到勝利,顯示提示文字并等待一次按鍵,返回勝利信息 { showText="白方獲得了勝利!"; Display(); if(getch()==0xE0) { getch(); } return Now; }else if(count==MAXIMUS*MAXIMUS)//如果回合數(shù)達到了棋盤總量,即棋盤充滿,即為平局 { showText="平局!"; Display(); if(getch()==0xE0) { getch(); } return 0; } } } else if(input==0xE0)//如果按下的是方向鍵,會填充兩次輸入,第一次為0xE0表示按下的是控制鍵 { input=getch();//獲得第二次輸入信息 switch(input)//判斷方向鍵方向并移動光標(biāo)位置 { case 0x4B:Cx--; break; case 0x48:Cy--;break; case 0x4D:Cx++;break; case 0x50:Cy++;break; } if(Cx<0)Cx=MAXIMUS-1;//如果光標(biāo)位置越界則移動到對側(cè) if(Cy<0)Cy=MAXIMUS-1; if(Cx>MAXIMUS-1)Cx=0; if(Cy>MAXIMUS-1)Cy=0; } } } int main()//主函數(shù) { system("title 五-子-棋 -- c語言(dotcpp.com)研究中心");//設(shè)置標(biāo)題 system("mode con cols=63 lines=32");//設(shè)置窗口大小 system("color E0");//設(shè)置顏色 while(1) {//循環(huán)執(zhí)行游戲 RunGame(); } }
C語言研究中心(www.sztianhecheng.cn)