#include "stdio.h"
#include "math.h"
#include "windows.h"
#include "time.h"//使用當前時鐘做種子
#define N 15 //定義棋盤大小 1黑2白
#define M N+8 //定義資料棋盤大小
int chess[N][N];//棋盤,用於儲存下子位置
int count[M][M];//資料棋盤,用於儲存下子位置,和盤外資料
char buffer[N*2-1][N*4-3];//緩衝器,用於儲存下子位置,盤外資料,和棋碟符號
long sum[M][M] = {{0}};//得分棋盤,儲存得分情況
int p[20][5];//儲存該位置的所有可能的五連珠情況
int player = 1, ai = 2, error = -1;
int num;//雙方回合總數
int now;//設定下棋標誌
int flag0;//確定己方已下子
int gs;//遊戲結束標誌
//基礎函式
void RunGame();//進行整個對局
int Menu();//設定開始選單
void Initialize();//初始化棋盤,資料棋盤,和緩衝器
void Print(int x, int y);//將資料寫入資料棋盤,和緩衝器
void Display();//將緩衝器資料輸出到螢幕
void Buf_Display();//利用雙緩衝將緩衝器資料輸出到螢幕
int Judge_Display();//輸出勝負情況
//雙方對局函式
void PGame();//玩家對局函式
void CGame();//電腦對局函式
//輸入函式
void Input(int *x, int *y);//鍵盤方向鍵控制,空格鍵輸入
void Mark(int x0, int y0, int x, int y);//標記下子位置
//電腦判斷函式
int Basic_condition(int x, int y);//判斷下子位置是否出界
void Find_point(int *pp, int *qq);//找到最佳性最優的下子位置
int JUDGE(int x, int y);//判斷勝負
void Grade();//計算所有位置的得分
int Base(int i, int j);//座標為(i-4,j-4)的所有五連珠情況
long Assessment(int num1, int num2);//評分標準
//主程式
int main()
{
system("title 簡易五子棋");//設定標題
system("mode con cols=58 lines=29");//設定視窗大小
system("color E0");//設定顏色
Initialize();//初始化棋盤,資料棋盤,和緩衝器
RunGame();//進行整個對局*/
return 0;
}
/***********************************************************************************************************************************************************/
void RunGame()//進行整個對局
switch(Menu())
case 1:
while(1)
PGame();//玩家對局函式
if(Judge_Display())
break;//對局結束
CGame();//電腦對局函式
}//while
break;
case 2:
now=ai;
count[N/2+4][N/2+4] = now; chess[N/2][N/2] = now;
Print(N/2, N/2);//將資料寫入資料棋盤,和緩衝器
num++;
if(Judge_Display())//玩家對局函式
case 3:
now=1;
default:;
int Menu()//設定開始選單
int x;
printf("1、玩家先手\n");
printf("2、玩家後手\n");
printf("3、電腦自對弈\n");
scanf("%d", &x);
return x;
void Initialize()//初始化棋盤,資料棋盤,和緩衝器
int i, j;
//初始化資料棋盤
for(i = 0; i < M; i++)
for(j = 0; j < M; j++)
if((i < 4 || i >= M - 4)&&(j < 4 || j>= M - 4))
count[i][j] = error;
//初始化緩衝器
for(i = 0; i < N*2-1; i++)
for(j = 0; j < N*4-3; j++)
if(i == 0 && j == 0)//以下為邊緣棋盤樣式
buffer[i][j]="a";//"┏";
else if(i == 0 && j == (N*4-3)-1)
buffer[i][j] = "b";//"┓";
else if(i == (N*2-1)-1 && j == (N*4-3)-1)
buffer[i][j] = "c";//"┛";
else if(i == (N*2-1)-1&&j == 0)
buffer[i][j]="d";//"┗";
else if(i == 0 && j % 4 == 0)
buffer[i][j]="e";//"┯";
else if(i == (N*2-1)-1 && j % 4 == 0)
buffer[i][j] = "f";//"┷";
else if(i % 2 == 0 && j == 0)
buffer[i][j] = "g";//"┠";
else if(i % 2 == 0 && j == (N*4-3)-1)
buffer[i][j] = "h";//"┨";
else if((i == 0 || i == (N*2-1)-1) && (j/2) % 2 != 0)
buffer[i][j] = "i";//"━";
else if(i != 0 && i != (N*2-1)-1 && i % 2 == 0 && (j/2) % 2 != 0)
buffer[i][j] = "j";//"—";
else if(i % 2 != 0 && (j == 0 || j == (N*4-3)-1))
buffer[i][j] = "k";//"┃";
else if(i % 2 != 0 && j != 0 && j != (N*4-3)-1 && j % 4 == 0)
buffer[i][j] = "l";//"│";
else if(i != 0 && j != 0 && i != (N*2-1)-1 && j != (N*4-3)-1 && i % 2 == 0 && j % 4 == 0)
buffer[i][j] = "m";//中間的空位"┼"
void Print(int x, int y)//將資料寫入資料棋盤,和緩衝器
count[x+4][y+4] = chess[x][y];
buffer[x*2][y*4] = chess[x][y] + 48;//將整型資料轉化為字元型資料
void Display()//將緩衝器資料輸出到螢幕
system("cls");//清理螢幕,準備寫入
// printf("%c", buffer[i][j]);
switch(buffer[i][j])
case "1" : printf("●"); j++; break;//j++不可省
case "2" : printf("○"); j++; break;//j++不可省
case "a" : printf("┏"); break;
case "b" : printf("┓"); break;
case "c" : printf("┛"); break;
case "d" : printf("┗"); break;
case "e" : printf("┯"); break;
case "f" : printf("┷"); break;
case "g" : printf("┠"); break;
case "h" : printf("┨"); break;
case "i" : printf("━"); break;//上下的橫線更粗
case "j" : printf("—"); j++; break;//中間的橫線更細//j++;由於輸出"—"時佔兩個字元,j++可以避開輸出下一個的空格
case "k" : printf("┃"); break;//左右的豎線更粗
case "l" : printf("│"); break;//中間的豎線更粗
case "m" : printf("┼"); break;
case " " : printf(" "); break;
default : printf("%c", buffer[i][j]);
}//switch
}//for
printf("\n");
Sleep(100);
/*
//除錯
printf("%d\n", num);
for(i = 4; i < M-4; i++)
for( j = 4; j < M-4; j++)
printf("%8d", sum[i][j]);
*/
void PGame()//玩家對局函式
static int Px0 = N/2, Py0 = N/2, Px = N/2, Py = N/2;
now = 1;
do{
Mark(Px0, Py0, Px, Py);//標記下子位置
Buf_Display();//將緩衝器資料輸出到螢幕
Px0 = Px; Py0 = Py;
Input(&Px, &Py);
}while(!(chess[Px][Py] && flag0 == 1));
Print(Px, Py);//將資料寫入資料棋盤,和緩衝器
gs = JUDGE(Px + 4,Py + 4);
void CGame()//電腦對局函式
static int Cp = N/2, Cq = N/2, Cp0, Cq0;
Grade();//計算所有位置的得分
Cp0 = Cp; Cq0 = Cq;//記錄上一次電腦下子位置
Find_point(&Cp, &Cq);//找到最佳性最優的下子位置
now = 3 - now;
chess[Cp - 4][Cq - 4] = now;
Mark(Cp0 - 4, Cq0 - 4, Cp - 4, Cq - 4);//標記下子位置
Print(Cp - 4, Cq - 4);//將資料寫入資料棋盤,和緩衝器
gs = JUDGE(Cp, Cq);
void Input(int *x, int *y)//鍵盤方向鍵控制,空格鍵輸入
int input;
flag0 = 0;
input = getch();//獲得第一次輸入資訊
if(input == 0x20 && !chess[*x][*y])//判斷移動游標後,玩家是否下子
chess[*x][*y] = player;
flag0 = 1;
else if(input == 0xE0)//如果按下的是方向鍵,會填充兩次輸入,第一次為0xE0表示按下的是控制鍵
input = getch();//獲得第二次輸入資訊
switch(input)//判斷方向鍵方向並移動游標位置
case 0x48 : (*x)--; break;
case 0x4B : (*y)--; break;
case 0x50 : (*x)++; break;
case 0x4D : (*y)++; break;
if(*x<0) (*x) = N - 1;//如果游標位置越界則移動到對側
if(*y<0) (*y) = N - 1;
if(*x>N-1) (*x) = 0;
if(*y>N-1) (*y) = 0;
void Mark(int x0,int y0,int x,int y)//標記己方下子位置
x0 = x0*2; y0 = y0*4;
buffer[x0 - 1][y0 - 2] = " ";
buffer[x0 - 1][y0 + 2] = " ";
buffer[x0 + 1][y0 + 2] = " ";
buffer[x0 + 1][y0 - 2] = " ";
x = x*2; y = y*4;
buffer[x - 1][y - 2] = "a";
buffer[x - 1][y + 2] = "b";
buffer[x + 1][y + 2] = "c";
buffer[x + 1][y - 2] = "d";
if(y == (N*4-3)-1)//解決“當游標移動到最右側時,游標發生錯位”
buffer[x - 1][y + 2] = " ";
buffer[x + 1][y + 2] = " ";
int Basic_condition(int x,int y)//判斷下子位置是否出界
if(x >= 4 && x < M - 4 && y >= 4 && y < M - 4)
return 1;
else
void Find_point(int *pp, int *qq)//找到最佳性最優的下子位置
int i, j, flag = 0;//flag為結束標誌
long t = 0;
int r, c=0, sumed[N*N][2];
//尋找第一個未下子位置對應的sum值
for(i = 4; i < M - 4 && flag == 0; i++)
for(j = 4; j < M - 4 && flag == 0; j++)
if(!chess[i - 4][j - 4])
t = sum[i][j];
flag = 1;
//尋找最大的sum值
for(i = 4; i < M - 4; i++)
for(j = 4; j < M - 4 ; j++)
if(!chess[i - 4][j - 4] && sum[i][j] > t)
//等於怎麼辦
//儲存所有的最大sum值
if(!chess[i - 4][j - 4] && sum[i][j] == t)
sumed[c][0] = i;
sumed[c][1] = j;
c++;
srand((unsigned)time(NULL)); //初始化隨機數
//隨機選用最大sum值中的一組資料
r = rand()%c;
*pp = sumed[r][0];
*qq = sumed[r][1];
int JUDGE(int x, int y)//判斷勝負,返回1贏,返回0無
int a = 1, b = 1, c = 1, d = 1, i;//累計橫豎正斜反斜四個方向的連續相同棋子數目
for(i=1;i<5;i++)if(y+i<M-4&&count[x][y+i]==now)a++;else break;//向下檢查
for(i=1;i<5;i++)if(y-i>=4&&count[x][y-i]==now)a++;else break;//向上檢查
if(a>=5)return now;//若達到5個則判斷當前走子玩家為贏家
for(i=1;i<5;i++)if(x+i<M-4&&count[x+i][y]==now)b++;else break;//向右檢查
for(i=1;i<5;i++)if(x-i>=4&&count[x-i][y]==now)b++;else break;//向左檢查
if(b>=5)return now;//若達到5個則判斷當前走子玩家為贏家
for(i=1;i<5;i++)if(x+i<M-4&&y+i<M-4&&count[x+i][y+i]==now)c++;else break;//向右下檢查
for(i=1;i<5;i++)if(x-i>=4&&y-i>=4&&count[x-i][y-i]==now)c++;else break;//向左上檢查
if(c>=5)return now;//若達到5個則判斷當前走子玩家為贏家
for(i=1;i<5;i++)if(x+i<M-4&&y-i>=4&&count[x+i][y-i]==now)d++;else break;//向右上檢查
for(i=1;i<5;i++)if(x-i>=4&&y+i<M-4&&count[x-i][y+i]==now)d++;else break;//向左下檢查
if(d>=5)return now;//若達到5個則判斷當前走子玩家為贏家
return 0;//若沒有檢查到五連珠,則返回0表示還沒有玩家達成勝利
void Grade()//計算所有位置的得分
int i, j, m, n;
int num1, num2;
for(j = 4; j < M - 4; j++)
sum[i][j] = 0;//迴圈初始化sum[i][j]
Base(i, j);//座標為(i-4,j-4)的所有五連珠情況
for(m = 0; m < 20; m++)
num1 = 0; num2 = 0;
for(n = 0; n < 5; n++)
if(p[m][n] == now)
num1++;
else if(p[m][n] == 3 - now)
num2++;
else if(p[m][n] == error)
num1 = error; num2 = error;
sum[i][j] += Assessment(num1, num2);
int Base(int i,int j)//座標為(i-4,j-4)的所有五連珠情況
//左上->右下
p[0][0]=count[i-4][j-4];p[0][1]=count[i-3][j-3];p[0][2]=count[i-2][j-2];p[0][3]=count[i-1][j-1];p[0][4]=count[i][j];
p[1][0]=count[i-3][j-3];p[1][1]=count[i-2][j-2];p[1][2]=count[i-1][j-1];p[1][3]=count[i][j];p[1][4]=count[i+1][j+1];
p[2][0]=count[i-2][j-2];p[2][1]=count[i-1][j-1];p[2][2]=count[i][j];p[2][3]=count[i+1][j+1];p[2][4]=count[i+2][j+2];
p[3][0]=count[i-1][j-1];p[3][1]=count[i][j];p[3][2]=count[i+1][j+1];p[3][3]=count[i+2][j+2];p[3][4]=count[i+3][j+3];
p[4][0]=count[i][j];p[4][1]=count[i+1][j+1];p[4][2]=count[i+2][j+2];p[4][3]=count[i+3][j+3];p[4][4]=count[i+4][j+4];
//上->下
p[5][0]=count[i-4][j];p[5][1]=count[i-3][j];p[5][2]=count[i-2][j];p[5][3]=count[i-1][j];p[5][4]=count[i][j];
p[6][0]=count[i-3][j];p[6][1]=count[i-2][j];p[6][2]=count[i-1][j];p[6][3]=count[i][j];p[6][4]=count[i+1][j];
p[7][0]=count[i-2][j];p[7][1]=count[i-1][j];p[7][2]=count[i][j];p[7][3]=count[i+1][j];p[7][4]=count[i+2][j];
p[8][0]=count[i-1][j];p[8][1]=count[i][j];p[8][2]=count[i+1][j];p[8][3]=count[i+2][j];p[8][4]=count[i+3][j];
p[9][0]=count[i][j];p[9][1]=count[i+1][j];p[9][2]=count[i+2][j];p[9][3]=count[i+3][j];p[9][4]=count[i+4][j];
//右上->左下
p[10][0]=count[i-4][j+4];p[10][1]=count[i-3][j+3];p[10][2]=count[i-2][j+2];p[10][3]=count[i-1][j+1];p[10][4]=count[i][j];
p[11][0]=count[i-3][j+3];p[11][1]=count[i-2][j+2];p[11][2]=count[i-1][j+1];p[11][3]=count[i][j];p[11][4]=count[i+1][j-1];
p[12][0]=count[i-2][j+2];p[12][1]=count[i-1][j+1];p[12][2]=count[i][j];p[12][3]=count[i+1][j-1];p[112][4]=count[i+2][j-2];
p[13][0]=count[i-1][j+1];p[13][1]=count[i][j];p[13][2]=count[i+1][j-1];p[13][3]=count[i+2][j-2];p[13][4]=count[i+3][j-3];
p[14][0]=count[i][j];p[14][1]=count[i+1][j-1];p[14][2]=count[i+2][j-2];p[14][3]=count[i+3][j-3];p[14][4]=count[i+4][j-4];
//左->右
p[15][0]=count[i][j-4];p[15][1]=count[i][j-3];p[15][2]=count[i][j-2];p[15][3]=count[i][j-1];p[15][4]=count[i][j];
p[16][0]=count[i][j-3];p[16][1]=count[i][j-2];p[16][2]=count[i][j-1];p[16][3]=count[i][j];p[16][4]=count[i][j+1];
p[17][0]=count[i][j-2];p[17][1]=count[i][j-1];p[17][2]=count[i][j];p[17][3]=count[i][j+1];p[17][4]=count[i][j+2];
p[18][0]=count[i][j-1];p[18][1]=count[i][j];p[18][2]=count[i][j+1];p[18][3]=count[i][j+2];p[18][4]=count[i][j+3];
p[19][0]=count[i][j];p[19][1]=count[i][j+1];p[19][2]=count[i][j+2];p[19][3]=count[i][j+3];p[19][4]=count[i][j+4];
long Assessment(int num1,int num2)//評分標準
if(num2 == 0)//判斷電腦五元組得分
switch(num1)
case 0 : return 7;
case 1 : return 35;
case 2 : return 800;
case 3 : return 15000;
case 4 : return 800000;
if(num2 != 0 && num1 == 0)//判斷玩家五元組得分
switch(num2)
case 1 : return 15;
case 2 : return 400;
case 3 : return 1800;
case 4 : return 100000;
void Buf_Display()//利用雙緩衝將緩衝器資料輸出到螢幕
//建立螢幕緩衝區
HANDLE hNewConsole = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL);
//隱藏游標
CONSOLE_CURSOR_INFO cci = {1, 0};
SetConsoleCursorInfo(hNewConsole, &cci);
//設定視窗的緩衝區大小
COORD cdBufferSize = {58, 29};
SetConsoleScreenBufferSize(hNewConsole, cdBufferSize);
//然後我們輸出這個陣列看看
COORD cdCursorPos = {j, i};
char *p = NULL;
case "1" : p = "●"; j++; break;//j++可省
case "2" : p = "○"; j++; break;//j++可省
case "a" : p = "┏"; break;
case "b" : p = "┓"; break;
case "c" : p = "┛"; break;
case "d" : p = "┗"; break;
case "e" : p = "┯"; break;
case "f" : p = "┷"; break;
case "g" : p = "┠"; break;
case "h" : p = "┨"; break;
case "i" : p = "━"; break;//上下的橫線更粗
case "j" : p = "—"; j++; break;//中間的橫線更細//j++;由於輸出"—"時佔兩個字元,j++可以避開輸出下一個的空格
case "k" : p = "┃"; break;//左右的豎線更粗
case "l" : p = "│"; break;//中間的豎線更粗
case "m" : p = "┼"; break;
case " " : p = " "; break;
default : p = &buffer[i][j];
}//switch,for
if( ! p) continue;
SetConsoleCursorPosition(hNewConsole, cdCursorPos);
WriteConsole(hNewConsole, p, strlen(p), NULL, NULL);
// printf("\n");
//把繪製好的東西都顯示出來
SetConsoleActiveScreenBuffer(hNewConsole);
//如果遊戲結束,返回正常模式
/* if(gs)
SetConsoleActiveScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE));
}*/
int Judge_Display()//輸出勝負情況
if(num == N*N)
printf("平局!\n");
return 1;//對局結束
if(gs == 1)
printf("黑棋贏!\n");
if(gs == 2)
printf("白棋贏!\n");
#include "stdio.h"
#include "math.h"
#include "windows.h"
#include "time.h"//使用當前時鐘做種子
#define N 15 //定義棋盤大小 1黑2白
#define M N+8 //定義資料棋盤大小
int chess[N][N];//棋盤,用於儲存下子位置
int count[M][M];//資料棋盤,用於儲存下子位置,和盤外資料
char buffer[N*2-1][N*4-3];//緩衝器,用於儲存下子位置,盤外資料,和棋碟符號
long sum[M][M] = {{0}};//得分棋盤,儲存得分情況
int p[20][5];//儲存該位置的所有可能的五連珠情況
int player = 1, ai = 2, error = -1;
int num;//雙方回合總數
int now;//設定下棋標誌
int flag0;//確定己方已下子
int gs;//遊戲結束標誌
//基礎函式
void RunGame();//進行整個對局
int Menu();//設定開始選單
void Initialize();//初始化棋盤,資料棋盤,和緩衝器
void Print(int x, int y);//將資料寫入資料棋盤,和緩衝器
void Display();//將緩衝器資料輸出到螢幕
void Buf_Display();//利用雙緩衝將緩衝器資料輸出到螢幕
int Judge_Display();//輸出勝負情況
//雙方對局函式
void PGame();//玩家對局函式
void CGame();//電腦對局函式
//輸入函式
void Input(int *x, int *y);//鍵盤方向鍵控制,空格鍵輸入
void Mark(int x0, int y0, int x, int y);//標記下子位置
//電腦判斷函式
int Basic_condition(int x, int y);//判斷下子位置是否出界
void Find_point(int *pp, int *qq);//找到最佳性最優的下子位置
int JUDGE(int x, int y);//判斷勝負
void Grade();//計算所有位置的得分
int Base(int i, int j);//座標為(i-4,j-4)的所有五連珠情況
long Assessment(int num1, int num2);//評分標準
//主程式
int main()
{
system("title 簡易五子棋");//設定標題
system("mode con cols=58 lines=29");//設定視窗大小
system("color E0");//設定顏色
Initialize();//初始化棋盤,資料棋盤,和緩衝器
RunGame();//進行整個對局*/
return 0;
}
/***********************************************************************************************************************************************************/
void RunGame()//進行整個對局
{
switch(Menu())
{
case 1:
while(1)
{
PGame();//玩家對局函式
if(Judge_Display())
{
break;//對局結束
}
CGame();//電腦對局函式
if(Judge_Display())
{
break;//對局結束
}
}//while
break;
case 2:
now=ai;
count[N/2+4][N/2+4] = now; chess[N/2][N/2] = now;
Print(N/2, N/2);//將資料寫入資料棋盤,和緩衝器
num++;
while(1)
{
PGame();//玩家對局函式
if(Judge_Display())//玩家對局函式
{
break;//對局結束
}
CGame();//電腦對局函式
if(Judge_Display())
{
break;//對局結束
}
}//while
break;
case 3:
now=1;
count[N/2+4][N/2+4] = now; chess[N/2][N/2] = now;
Print(N/2, N/2);//將資料寫入資料棋盤,和緩衝器
num++;
while(1)
{
CGame();//電腦對局函式
if(Judge_Display())
{
break;//對局結束
}
}
break;
default:;
}
}
/***********************************************************************************************************************************************************/
int Menu()//設定開始選單
{
int x;
printf("1、玩家先手\n");
printf("2、玩家後手\n");
printf("3、電腦自對弈\n");
scanf("%d", &x);
return x;
}
void Initialize()//初始化棋盤,資料棋盤,和緩衝器
{
int i, j;
//初始化資料棋盤
for(i = 0; i < M; i++)
{
for(j = 0; j < M; j++)
{
if((i < 4 || i >= M - 4)&&(j < 4 || j>= M - 4))
{
count[i][j] = error;
}
}
}
//初始化緩衝器
for(i = 0; i < N*2-1; i++)
{
for(j = 0; j < N*4-3; j++)
{
if(i == 0 && j == 0)//以下為邊緣棋盤樣式
buffer[i][j]="a";//"┏";
else if(i == 0 && j == (N*4-3)-1)
buffer[i][j] = "b";//"┓";
else if(i == (N*2-1)-1 && j == (N*4-3)-1)
buffer[i][j] = "c";//"┛";
else if(i == (N*2-1)-1&&j == 0)
buffer[i][j]="d";//"┗";
else if(i == 0 && j % 4 == 0)
buffer[i][j]="e";//"┯";
else if(i == (N*2-1)-1 && j % 4 == 0)
buffer[i][j] = "f";//"┷";
else if(i % 2 == 0 && j == 0)
buffer[i][j] = "g";//"┠";
else if(i % 2 == 0 && j == (N*4-3)-1)
buffer[i][j] = "h";//"┨";
else if((i == 0 || i == (N*2-1)-1) && (j/2) % 2 != 0)
buffer[i][j] = "i";//"━";
else if(i != 0 && i != (N*2-1)-1 && i % 2 == 0 && (j/2) % 2 != 0)
buffer[i][j] = "j";//"—";
else if(i % 2 != 0 && (j == 0 || j == (N*4-3)-1))
buffer[i][j] = "k";//"┃";
else if(i % 2 != 0 && j != 0 && j != (N*4-3)-1 && j % 4 == 0)
buffer[i][j] = "l";//"│";
else if(i != 0 && j != 0 && i != (N*2-1)-1 && j != (N*4-3)-1 && i % 2 == 0 && j % 4 == 0)
buffer[i][j] = "m";//中間的空位"┼"
}
}
}
void Print(int x, int y)//將資料寫入資料棋盤,和緩衝器
{
count[x+4][y+4] = chess[x][y];
buffer[x*2][y*4] = chess[x][y] + 48;//將整型資料轉化為字元型資料
}
void Display()//將緩衝器資料輸出到螢幕
{
int i, j;
system("cls");//清理螢幕,準備寫入
for(i = 0; i < N*2-1; i++)
{
for(j = 0; j < N*4-3; j++)
{
// printf("%c", buffer[i][j]);
switch(buffer[i][j])
{
case "1" : printf("●"); j++; break;//j++不可省
case "2" : printf("○"); j++; break;//j++不可省
case "a" : printf("┏"); break;
case "b" : printf("┓"); break;
case "c" : printf("┛"); break;
case "d" : printf("┗"); break;
case "e" : printf("┯"); break;
case "f" : printf("┷"); break;
case "g" : printf("┠"); break;
case "h" : printf("┨"); break;
case "i" : printf("━"); break;//上下的橫線更粗
case "j" : printf("—"); j++; break;//中間的橫線更細//j++;由於輸出"—"時佔兩個字元,j++可以避開輸出下一個的空格
case "k" : printf("┃"); break;//左右的豎線更粗
case "l" : printf("│"); break;//中間的豎線更粗
case "m" : printf("┼"); break;
case " " : printf(" "); break;
default : printf("%c", buffer[i][j]);
}//switch
}//for
printf("\n");
}//for
Sleep(100);
/*
//除錯
printf("%d\n", num);
for(i = 4; i < M-4; i++)
{
for( j = 4; j < M-4; j++)
printf("%8d", sum[i][j]);
printf("\n");
}
*/
}
void PGame()//玩家對局函式
{
static int Px0 = N/2, Py0 = N/2, Px = N/2, Py = N/2;
now = 1;
do{
Mark(Px0, Py0, Px, Py);//標記下子位置
Buf_Display();//將緩衝器資料輸出到螢幕
Px0 = Px; Py0 = Py;
Input(&Px, &Py);
}while(!(chess[Px][Py] && flag0 == 1));
Print(Px, Py);//將資料寫入資料棋盤,和緩衝器
num++;
gs = JUDGE(Px + 4,Py + 4);
}
void CGame()//電腦對局函式
{
static int Cp = N/2, Cq = N/2, Cp0, Cq0;
Buf_Display();//將緩衝器資料輸出到螢幕
Grade();//計算所有位置的得分
Cp0 = Cp; Cq0 = Cq;//記錄上一次電腦下子位置
Find_point(&Cp, &Cq);//找到最佳性最優的下子位置
now = 3 - now;
chess[Cp - 4][Cq - 4] = now;
Mark(Cp0 - 4, Cq0 - 4, Cp - 4, Cq - 4);//標記下子位置
Print(Cp - 4, Cq - 4);//將資料寫入資料棋盤,和緩衝器
num++;
gs = JUDGE(Cp, Cq);
}
void Input(int *x, int *y)//鍵盤方向鍵控制,空格鍵輸入
{
int input;
flag0 = 0;
input = getch();//獲得第一次輸入資訊
if(input == 0x20 && !chess[*x][*y])//判斷移動游標後,玩家是否下子
{
chess[*x][*y] = player;
flag0 = 1;
}
else if(input == 0xE0)//如果按下的是方向鍵,會填充兩次輸入,第一次為0xE0表示按下的是控制鍵
{
input = getch();//獲得第二次輸入資訊
switch(input)//判斷方向鍵方向並移動游標位置
{
case 0x48 : (*x)--; break;
case 0x4B : (*y)--; break;
case 0x50 : (*x)++; break;
case 0x4D : (*y)++; break;
}//switch
if(*x<0) (*x) = N - 1;//如果游標位置越界則移動到對側
if(*y<0) (*y) = N - 1;
if(*x>N-1) (*x) = 0;
if(*y>N-1) (*y) = 0;
}
}
void Mark(int x0,int y0,int x,int y)//標記己方下子位置
{
x0 = x0*2; y0 = y0*4;
buffer[x0 - 1][y0 - 2] = " ";
buffer[x0 - 1][y0 + 2] = " ";
buffer[x0 + 1][y0 + 2] = " ";
buffer[x0 + 1][y0 - 2] = " ";
x = x*2; y = y*4;
buffer[x - 1][y - 2] = "a";
buffer[x - 1][y + 2] = "b";
buffer[x + 1][y + 2] = "c";
buffer[x + 1][y - 2] = "d";
if(y == (N*4-3)-1)//解決“當游標移動到最右側時,游標發生錯位”
{
buffer[x - 1][y + 2] = " ";
buffer[x + 1][y + 2] = " ";
}
}
int Basic_condition(int x,int y)//判斷下子位置是否出界
{
if(x >= 4 && x < M - 4 && y >= 4 && y < M - 4)
{
return 1;
}
else
{
return 0;
}
}
void Find_point(int *pp, int *qq)//找到最佳性最優的下子位置
{
int i, j, flag = 0;//flag為結束標誌
long t = 0;
int r, c=0, sumed[N*N][2];
//尋找第一個未下子位置對應的sum值
for(i = 4; i < M - 4 && flag == 0; i++)
{
for(j = 4; j < M - 4 && flag == 0; j++)
{
if(!chess[i - 4][j - 4])
{
t = sum[i][j];
flag = 1;
}
}
}//for
//尋找最大的sum值
for(i = 4; i < M - 4; i++)
{
for(j = 4; j < M - 4 ; j++)
{
if(!chess[i - 4][j - 4] && sum[i][j] > t)
{
t = sum[i][j];
}
}
}//for
//等於怎麼辦
//儲存所有的最大sum值
for(i = 4; i < M - 4; i++)
{
for(j = 4; j < M - 4 ; j++)
{
if(!chess[i - 4][j - 4] && sum[i][j] == t)
{
sumed[c][0] = i;
sumed[c][1] = j;
c++;
}
}
}//for
srand((unsigned)time(NULL)); //初始化隨機數
//隨機選用最大sum值中的一組資料
r = rand()%c;
*pp = sumed[r][0];
*qq = sumed[r][1];
}
int JUDGE(int x, int y)//判斷勝負,返回1贏,返回0無
{
int a = 1, b = 1, c = 1, d = 1, i;//累計橫豎正斜反斜四個方向的連續相同棋子數目
for(i=1;i<5;i++)if(y+i<M-4&&count[x][y+i]==now)a++;else break;//向下檢查
for(i=1;i<5;i++)if(y-i>=4&&count[x][y-i]==now)a++;else break;//向上檢查
if(a>=5)return now;//若達到5個則判斷當前走子玩家為贏家
for(i=1;i<5;i++)if(x+i<M-4&&count[x+i][y]==now)b++;else break;//向右檢查
for(i=1;i<5;i++)if(x-i>=4&&count[x-i][y]==now)b++;else break;//向左檢查
if(b>=5)return now;//若達到5個則判斷當前走子玩家為贏家
for(i=1;i<5;i++)if(x+i<M-4&&y+i<M-4&&count[x+i][y+i]==now)c++;else break;//向右下檢查
for(i=1;i<5;i++)if(x-i>=4&&y-i>=4&&count[x-i][y-i]==now)c++;else break;//向左上檢查
if(c>=5)return now;//若達到5個則判斷當前走子玩家為贏家
for(i=1;i<5;i++)if(x+i<M-4&&y-i>=4&&count[x+i][y-i]==now)d++;else break;//向右上檢查
for(i=1;i<5;i++)if(x-i>=4&&y+i<M-4&&count[x-i][y+i]==now)d++;else break;//向左下檢查
if(d>=5)return now;//若達到5個則判斷當前走子玩家為贏家
return 0;//若沒有檢查到五連珠,則返回0表示還沒有玩家達成勝利
}
void Grade()//計算所有位置的得分
{
int i, j, m, n;
int num1, num2;
for(i = 4; i < M - 4; i++)
{
for(j = 4; j < M - 4; j++)
{
if(!chess[i - 4][j - 4])
{
sum[i][j] = 0;//迴圈初始化sum[i][j]
Base(i, j);//座標為(i-4,j-4)的所有五連珠情況
for(m = 0; m < 20; m++)
{
num1 = 0; num2 = 0;
for(n = 0; n < 5; n++)
{
if(p[m][n] == now)
num1++;
else if(p[m][n] == 3 - now)
num2++;
else if(p[m][n] == error)
{
num1 = error; num2 = error;
break;
}
}
sum[i][j] += Assessment(num1, num2);
}
}
}
}
}
int Base(int i,int j)//座標為(i-4,j-4)的所有五連珠情況
{
//左上->右下
p[0][0]=count[i-4][j-4];p[0][1]=count[i-3][j-3];p[0][2]=count[i-2][j-2];p[0][3]=count[i-1][j-1];p[0][4]=count[i][j];
p[1][0]=count[i-3][j-3];p[1][1]=count[i-2][j-2];p[1][2]=count[i-1][j-1];p[1][3]=count[i][j];p[1][4]=count[i+1][j+1];
p[2][0]=count[i-2][j-2];p[2][1]=count[i-1][j-1];p[2][2]=count[i][j];p[2][3]=count[i+1][j+1];p[2][4]=count[i+2][j+2];
p[3][0]=count[i-1][j-1];p[3][1]=count[i][j];p[3][2]=count[i+1][j+1];p[3][3]=count[i+2][j+2];p[3][4]=count[i+3][j+3];
p[4][0]=count[i][j];p[4][1]=count[i+1][j+1];p[4][2]=count[i+2][j+2];p[4][3]=count[i+3][j+3];p[4][4]=count[i+4][j+4];
//上->下
p[5][0]=count[i-4][j];p[5][1]=count[i-3][j];p[5][2]=count[i-2][j];p[5][3]=count[i-1][j];p[5][4]=count[i][j];
p[6][0]=count[i-3][j];p[6][1]=count[i-2][j];p[6][2]=count[i-1][j];p[6][3]=count[i][j];p[6][4]=count[i+1][j];
p[7][0]=count[i-2][j];p[7][1]=count[i-1][j];p[7][2]=count[i][j];p[7][3]=count[i+1][j];p[7][4]=count[i+2][j];
p[8][0]=count[i-1][j];p[8][1]=count[i][j];p[8][2]=count[i+1][j];p[8][3]=count[i+2][j];p[8][4]=count[i+3][j];
p[9][0]=count[i][j];p[9][1]=count[i+1][j];p[9][2]=count[i+2][j];p[9][3]=count[i+3][j];p[9][4]=count[i+4][j];
//右上->左下
p[10][0]=count[i-4][j+4];p[10][1]=count[i-3][j+3];p[10][2]=count[i-2][j+2];p[10][3]=count[i-1][j+1];p[10][4]=count[i][j];
p[11][0]=count[i-3][j+3];p[11][1]=count[i-2][j+2];p[11][2]=count[i-1][j+1];p[11][3]=count[i][j];p[11][4]=count[i+1][j-1];
p[12][0]=count[i-2][j+2];p[12][1]=count[i-1][j+1];p[12][2]=count[i][j];p[12][3]=count[i+1][j-1];p[112][4]=count[i+2][j-2];
p[13][0]=count[i-1][j+1];p[13][1]=count[i][j];p[13][2]=count[i+1][j-1];p[13][3]=count[i+2][j-2];p[13][4]=count[i+3][j-3];
p[14][0]=count[i][j];p[14][1]=count[i+1][j-1];p[14][2]=count[i+2][j-2];p[14][3]=count[i+3][j-3];p[14][4]=count[i+4][j-4];
//左->右
p[15][0]=count[i][j-4];p[15][1]=count[i][j-3];p[15][2]=count[i][j-2];p[15][3]=count[i][j-1];p[15][4]=count[i][j];
p[16][0]=count[i][j-3];p[16][1]=count[i][j-2];p[16][2]=count[i][j-1];p[16][3]=count[i][j];p[16][4]=count[i][j+1];
p[17][0]=count[i][j-2];p[17][1]=count[i][j-1];p[17][2]=count[i][j];p[17][3]=count[i][j+1];p[17][4]=count[i][j+2];
p[18][0]=count[i][j-1];p[18][1]=count[i][j];p[18][2]=count[i][j+1];p[18][3]=count[i][j+2];p[18][4]=count[i][j+3];
p[19][0]=count[i][j];p[19][1]=count[i][j+1];p[19][2]=count[i][j+2];p[19][3]=count[i][j+3];p[19][4]=count[i][j+4];
}
long Assessment(int num1,int num2)//評分標準
{
if(num2 == 0)//判斷電腦五元組得分
{
switch(num1)
{
case 0 : return 7;
case 1 : return 35;
case 2 : return 800;
case 3 : return 15000;
case 4 : return 800000;
}
}
if(num2 != 0 && num1 == 0)//判斷玩家五元組得分
{
switch(num2)
{
case 1 : return 15;
case 2 : return 400;
case 3 : return 1800;
case 4 : return 100000;
}
}
return 0;
}
void Buf_Display()//利用雙緩衝將緩衝器資料輸出到螢幕
{
int i, j;
//建立螢幕緩衝區
HANDLE hNewConsole = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ,
0,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL);
//隱藏游標
CONSOLE_CURSOR_INFO cci = {1, 0};
SetConsoleCursorInfo(hNewConsole, &cci);
//設定視窗的緩衝區大小
COORD cdBufferSize = {58, 29};
SetConsoleScreenBufferSize(hNewConsole, cdBufferSize);
//然後我們輸出這個陣列看看
for(i = 0; i < N*2-1; i++)
{
for(j = 0; j < N*4-3; j++)
{
COORD cdCursorPos = {j, i};
char *p = NULL;
// printf("%c", buffer[i][j]);
switch(buffer[i][j])
{
case "1" : p = "●"; j++; break;//j++可省
case "2" : p = "○"; j++; break;//j++可省
case "a" : p = "┏"; break;
case "b" : p = "┓"; break;
case "c" : p = "┛"; break;
case "d" : p = "┗"; break;
case "e" : p = "┯"; break;
case "f" : p = "┷"; break;
case "g" : p = "┠"; break;
case "h" : p = "┨"; break;
case "i" : p = "━"; break;//上下的橫線更粗
case "j" : p = "—"; j++; break;//中間的橫線更細//j++;由於輸出"—"時佔兩個字元,j++可以避開輸出下一個的空格
case "k" : p = "┃"; break;//左右的豎線更粗
case "l" : p = "│"; break;//中間的豎線更粗
case "m" : p = "┼"; break;
case " " : p = " "; break;
default : p = &buffer[i][j];
}//switch,for
if( ! p) continue;
SetConsoleCursorPosition(hNewConsole, cdCursorPos);
WriteConsole(hNewConsole, p, strlen(p), NULL, NULL);
}
// printf("\n");
}//for
//把繪製好的東西都顯示出來
SetConsoleActiveScreenBuffer(hNewConsole);
//如果遊戲結束,返回正常模式
/* if(gs)
{
SetConsoleActiveScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE));
}*/
}
int Judge_Display()//輸出勝負情況
{
if(num == N*N)
{
Buf_Display();//將緩衝器資料輸出到螢幕
printf("平局!\n");
return 1;//對局結束
}
if(gs == 1)
{
Buf_Display();//將緩衝器資料輸出到螢幕
printf("黑棋贏!\n");
return 1;//對局結束
}
if(gs == 2)
{
Buf_Display();//將緩衝器資料輸出到螢幕
printf("白棋贏!\n");
return 1;//對局結束
}
return 0;
}