三子棋小遊戲(C語言實現)
C語言打造簡單的三子棋小遊戲
簡單三子棋是指棋盤為3*3,玩家與電腦之間對決的遊戲。
話不多說,先上圖:其中‘0’代表電腦落子,‘X’:玩家落子
基本思路:
1.列印地圖(列印一個“#”字狀的棋盤)
2.電腦落子(隨機落子)
3.玩家落子(通過輸入座標的方式)
4判斷遊戲結果
程式碼及註釋:
game.h檔案
#ifndef _GAME_H__ #define _GAME_H__ #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define ROW 3 #define COL 3 void play_game(); void init(char map[ROW][COL], int row, int col); //地圖3*3的矩陣; void display(char map[ROW][COL], int row, int col); //輸出地圖 void player_move(char map[ROW][COL], int row, int col); //玩家移動函式 void computer_move(char map[ROW][COL], int row, int col);//電腦移動函式 char is_full(char map[ROW][COL], int row, int col);//棋盤是否已滿 char is_win(char map[ROW][COL], int row, int col);//判斷遊戲結果 #endif
game.c檔案
#include"game.h" //初始化地圖,用9個空格 void init(char map[ROW][COL], int row, int col) { memset(&map[0][0], ' ', row*col*sizeof(map[0][0])); } //顯示函式,向螢幕列印地圖 void display(char map[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { printf(" %c ", map[i][j]); if (j < col - 1) printf("|"); } printf("\n"); if (i < row - 1) { for (j = 0; j < col; j++) { printf(" ---"); /*if (j< col - 1) printf("|");*/ } printf("\n"); } } } //玩家落子,通過座標的形式 void player_move(char map[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("輪玩家走:"); while (1) { scanf("%d%d", &x, &y); if (1 <= x&&x <= row && 1 <= y&&y <= col)//確定座標界限 { if (map[x - 1][y - 1] == ' ')//判斷該位置是否為空 { map[x - 1][y - 1] = 'X'; break;//落子成功直接跳出這個落子的迴圈 } else printf("該座標已被佔用,請重新輸入:"); } else printf("輸入有誤,請重新輸入;"); } } void computer_move(char map[ROW][COL], int row, int col) { int x = 0; int y = 0; printf("輪電腦走:\n"); while (1) { x = rand() % row;//電腦落子,範圍0--2 y = rand() % col;//電腦落子,範圍0--2; //printf("x=%d,y=%d\n", x, y);電腦走的座標 if (map[1][1] == ' ') { map[1][1] = '0'; break; } else if (map[x][y] == ' ')//判斷是否為空格,如果是直接落子,否則重新生成隨機座標座標 { map[x][y] = '0'; break; } } } char is_full(char map[ROW][COL], int row, int col) { int i = 0; int j = 0; int count = row*col;//總的棋盤格子 for (i = 0; i < row; i++)//判斷是否平局,即9個格子全滿 { for (j = 0; j < col; j++) { if (map[i][j] == 'X' || map[i][j] == '0') count--; } } if (count == 0) return '1'; } char is_win(char map[ROW][COL], int row, int col) { int i = 0; int j = 0; char ret = 0; ret = is_full(map, ROW, COL); for (i = 0; i < row; i++) { //判斷每一行的row個是否相等 if (map[i][0] == map[i][1] && map[i][1] == map[i][2] && map[i][0] != ' ') return map[i][0]; } //判斷每一列的col個是否相等 for (j = 0; j < col; j++) { if (map[0][j] == map[1][j] && map[1][j] == map[2][j] && map[1][j] != ' ') return map[0][j]; } //判斷主對角線 if (map[0][0] == map[1][1] && map[1][1] == map[2][2] && map[2][2] != ' ') return map[1][1]; //判斷次對角線 if (map[0][2] == map[1][1] && map[1][1] == map[2][0] && map[1][1] != ' ') return map[1][1]; //判斷平局 if (ret =='1') { return 'p'; } }
test.c檔案
#define _CRT_SECURE_NO_WARNINGS 2 #include"game.h" void menu() { printf("************************\n"); printf("********1 : PLAY********\n"); printf("********0 : EXIT********\n"); printf("************************\n"); } void play_game() { char ret = 0; char map[ROW][COL] = { 0 }; init(map, ROW, COL); //display(map, ROW, COL); while (1) { computer_move(map, ROW, COL); display(map, ROW, COL); ret=is_win(map, ROW, COL); //printf("%c\n", ret); if (ret == 'X') { printf("玩家贏!\n"); break; } else if (ret == '0') { printf("電腦贏!\n"); break; } else if (ret == 'p') { printf("平局\n"); break; } else ; player_move(map, ROW, COL); system("cls"); display(map, ROW, COL); ret=is_win(map, ROW, COL); //printf("%c\n", ret); if (ret == 'X') { printf("玩家贏!\n"); break; } if (ret == '0') { printf("電腦贏!\n"); break; } if (ret == 'p') { printf("平局\n"); break; } } } int main() { char map[ROW][COL] = { 0 }; int input = 0; srand((unsigned)time(NULL)); do { menu(); printf("請選擇:"); scanf("%d", &input); switch (input) { case 1: play_game(); break; case 0: printf("退出遊戲!"); break; default: printf("輸入有誤,請重新選擇!\n"); break; } } while (input); system("pause"); return 0; }
逐步進行說明:
do
{
menu();
printf("請選擇:");
scanf("%d", &input);
switch (input)
{
case 1:
play_game();
break;
case 0:
printf("退出遊戲!");
break;
default:
printf("輸入有誤,請重新選擇!\n");
break;
}
} while (input);
遊戲至少要玩一局,因此在開始使用一個do…while迴圈顯得更加合理。接下來我們設計一個選單函式,讓黑白的介面顯得不那麼單調,如圖:
選單函式程式碼:
void menu()
{
printf("************************\n");
printf("********1 : PLAY********\n");
printf("********0 : EXIT********\n");
printf("************************\n");
}
是不是還可以而且特別簡單,在這裡玩家可以自己選擇是玩遊戲,還是退出遊戲!為了稍微加點遊戲難度,我們設定讓電腦先落子,並且第一次就在正中間落子!然後就該玩家落子了:
程式碼:
void player_move(char map[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("輪玩家走:");
while (1)
{
scanf("%d%d", &x, &y);
if (1 <= x&&x <= row && 1 <= y&&y <= col)//確定座標界限
{
if (map[x - 1][y - 1] == ' ')//判斷該位置是否為空
{
map[x - 1][y - 1] = 'X';
break;//落子成功直接跳出這個落子的迴圈
}
else
printf("該座標已被佔用,請重新輸入:");
}
else
printf("輸入有誤,請重新輸入;");
}
}
我們設計一個死迴圈,只有當玩家輸入正確的座標時,才能跳出這個迴圈。這裡輸入後首先要判斷行和列是不是在1—3這個範圍內,其次還要判斷玩家輸入的這個座標是否為空,滿足這幾點要求,方能正確落子,否則提醒玩家重新進行輸入!
判斷棋盤是否已滿:
char is_full(char map[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
int count = row*col;//總的棋盤格子
for (i = 0; i < row; i++)//判斷是否平局,即9個格子全滿
{
for (j = 0; j < col; j++)
{
if (map[i][j] == 'X' || map[i][j] == '0')
count--;
}
}
if (count == 0)
return '1';
}
我們遍歷整個二維陣列,並且設定一個count代表棋盤的格子數目,當棋盤上的格子為‘0’或‘X’是count-1,當count減到0的時候代表棋盤已經滿了並且返回一個‘1’。
判斷遊戲結果:
char is_win(char map[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
char ret = 0;
ret = is_full(map, ROW, COL);
for (i = 0; i < row; i++)
{
//判斷每一行的row個是否相等
if (map[i][0] == map[i][1] && map[i][1] == map[i][2] && map[i][0] != ' ')
return map[i][0];
}
//判斷每一列的col個是否相等
for (j = 0; j < col; j++)
{
if (map[0][j] == map[1][j] && map[1][j] == map[2][j] && map[1][j] != ' ')
return map[0][j];
}
//判斷主對角線
if (map[0][0] == map[1][1] && map[1][1] == map[2][2] && map[2][2] != ' ')
return map[1][1];
//判斷次對角線
if (map[0][2] == map[1][1] && map[1][1] == map[2][0] && map[1][1] != ' ')
return map[1][1];
//判斷平局
if (ret =='1')
{
return 'p';
}
}
遊戲結果總共有三種情況,輸,贏,平局,輸和贏判斷一個就夠了,玩家或電腦每次落子後我們遍歷整個陣列,看橫三或豎三或斜三是不是同一種字元,如果是則根據字元給出相應的遊戲結果,否則遊戲繼續!
前面我們判斷了棋盤滿的情況,當棋盤滿了且雙方都沒有贏就說明遊戲平局。遊戲結束!
電腦落子:電腦隨意落子,只要座標合法即可,程式碼:
`void computer_move(char map[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("輪電腦走:\n");
while (1)
{
x = rand() % row;//電腦落子,範圍0--2
y = rand() % col;//電腦落子,範圍0--2;
//printf("x=%d,y=%d\n", x, y);電腦走的座標
if (map[1][1] == ' ')
{
map[1][1] = '0';
break;
}
else if (map[x][y] == ' ')//判斷是否為空格,如果是直接落子,否則重新生成隨機座標座標
{
map[x][y] = '0';
break;
}
}
}`
在這裡我們使用rand,srand函式產生隨機值(範圍0–2),並判斷座標是否合法,合法即落子,否則的話重新生成隨機數座標。
總結:通過編寫這個小遊戲提升了我的程式設計能力,掌握了函式功能的劃分方法。提高了對知識的理解和運用能力,同時也發現自身的很多不足之處,值得好好思考!