用C語言來寫游戲是我們剛開始學C語言的時候樸素而又美好的愿望,現在我們就工程化,模塊化來寫一個三子棋的小游戲,要注意的是,電腦模擬部分是比較智障的;VS系列如VS2019等軟體寫專案是比較方便的,
一,構思
為了方便,我們寫test.c的源檔案用來測驗;寫game.h的頭檔案用來定義函式及包含頭檔案;寫game.c的源檔案用來寫游戲的主體部分,
1,對于一個三子棋游戲,要設定它的選單來決定是否游戲還是退出,設定游戲頁面,也就是棋盤部分,還需要一個游戲介面來進行游戲將他們放在test.c的源檔案里面,
2,三子棋游戲要先列印棋盤,待棋盤列印出來后需要對棋盤進行初始化,也就是將棋盤里的內容清空;然后設定玩家下棋的函式,電腦下棋的函式,隨后就是輸贏的判斷,將他們放在game.c的源檔案中,
3,由于工程化寫代碼,函式在源檔案之間呼叫的時候,需要一個頭檔案來包含庫中的頭檔案和函式的宣告,將他們放在game.h的頭檔案中,
二,具體步驟及代碼
1,game.h頭檔案部分
包含頭檔案,定義行數,列數,及函式的宣告,本游戲用二維陣列來寫,游戲主要的函式傳值需要傳三子棋的行數(ROW),列數(COL)及二維陣列,同時,為了理解的方便,二維陣列不寫成指標的形式,這部分完整代碼如下:
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define ROW 3
#define COL 3
//初始化棋盤
void initboard(char board[ROW][COL], int row, int col);
//列印棋盤
void displayboard(char board[ROW][COL], int row, int col);
//玩家下棋
void player_move(char board[ROW][COL], int row, int col);
//電腦下棋
void computer_move(char board[ROW][COL], int row, int col);
//判斷輸贏
//玩家贏--'*'
//電腦贏--'#'
//平均--'Q'
//繼續--'C'
char is_win(char board[ROW][COL], int row, int col);
2,test.c源檔案部分
先呼叫一次menu()函式來列印選單來提示玩家,將他放在test()函式里面,呼叫test()函式來選擇是游戲還是退出,若選擇1,則進入游戲部分,選擇0(假)退出,否則提示選擇錯誤,menu()部分代碼如下:
void menu()
{
printf("********************\n");
printf("**** 1. play *****\n");
printf("**** 0. exit *****\n");
printf("********************\n");
}
test()部分代碼如下:
void test()
{
int input = 0;//輸入值來選擇
srand((size_t)time(NULL));//隨機電腦下棋的位置,和rand函式配套使用,
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤\n");
break;
}
}while (input);
}
之后,就進入游戲的主體部分game()函式;這部分里面我們要,列印棋盤,對棋盤進行初始化,讓玩家下棋,讓電腦下棋,判斷棋盤的情況,判斷輸贏的情況,通過回傳的值來確定誰輸誰贏,代碼如下:
void game()
{
char board[ROW][COL] = { 0 };
initboard(board, ROW, COL);
displayboard(board, ROW, COL);
char ret = 0;
while(1)
{
player_move(board, ROW, COL);
displayboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
computer_move(board, ROW, COL);
displayboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家贏\n");
}
else if (ret == '#')
{
printf("電腦贏\n");
}
else
{
printf("平局\n");
}
}
完整代碼如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("********************\n");
printf("**** 1. play *****\n");
printf("**** 0. exit *****\n");
printf("********************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
initboard(board, ROW, COL);
displayboard(board, ROW, COL);
char ret = 0;
while(1)
{
player_move(board, ROW, COL);
displayboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
computer_move(board, ROW, COL);
displayboard(board, ROW, COL);
ret = is_win(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家贏\n");
}
else if (ret == '#')
{
printf("電腦贏\n");
}
else
{
printf("平局\n");
}
}
void test()
{
int input = 0;
srand((size_t)time(NULL));
do
{
menu();
printf("請選擇:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戲\n");
break;
default:
printf("選擇錯誤\n");
break;
}
}while (input);
}
int main(void)
{
test();
return 0;
}
3,game.c部分
1)列印棋盤,對圖片進行分析可知:棋盤是由“---”及“|”組成,符號部分是“(空格)*(空格)”,



利用for回圈,每行每列,交映的打出“ * ”,“---”和“|”,在最后一列“---”完成之后不需要列印“|”,要注意列印“|”的回圈條件,代碼如下:
void displayboard(char board[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 ", board[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");
}
}
2)對棋盤進行初始化:由于列印的字符是保存在二維陣列之中的,而且剛開始的時候,棋盤看起來是空的,可以用列印空格使它看起來是空的,對二維陣列,,用兩層for回圈進行遍歷,代碼如下:
void initboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
3)玩家下棋:
玩家輸入行,列來將字符放置在棋盤之中,由于陣列的下標從0開始,而玩家的習慣從1開始,故玩家輸入的值可能會導致陣列越界,而且,還要保證玩家輸入的行,列是在棋盤里面,就需要加一個判斷條件,如果不在棋盤里面,提示非法輸入,同樣的,在棋盤里面,玩家輸入的位置可能有了符號,所以需要在加一個判斷,若為空格,則放進去,否則提示被占用,代碼如下:
void player_move(char board[ROW][COL], int row, int col)
{
printf("玩家下棋:>");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("該坐標被占用,請重新輸入!\n");
}
}
else
{
printf("坐標非法!請重新輸入!\n");
}
}
}
4)電腦下棋:
電腦下棋的主要部分和玩家下棋是一樣的,區別是電腦下棋需要rand 函式進行模擬,代碼如下:
void computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦下棋:>\n");
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
5)判斷輸贏
判斷一行或一列,對角線是否滿足條件,若滿足,則回傳這個里面的字符作為判斷的依據,還有一種情況就是棋盤滿了,但沒有滿足條件的(平局),這部分呢需要放在判斷輸贏的后面,前兩者不成立,自然它就成立,故這部分只需要判斷棋盤里面有沒有空格就可以,代碼如下:
輸贏部分:
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
if (1 == is_full(board, row, col))
{
return 'Q';
}
return 'C';
}
平區域分:
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
完整代碼如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void initboard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void displayboard(char board[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 ", board[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 board[ROW][COL], int row, int col)
{
printf("玩家下棋:>");
int x = 0;
int y = 0;
while (1)
{
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("該坐標被占用,請重新輸入!\n");
}
}
else
{
printf("坐標非法!請重新輸入!\n");
}
}
}
void computer_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("電腦下棋:>\n");
while (1)
{
x = rand() % ROW;
y = rand() % COL;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
int is_full(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char is_win(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
{
return board[i][1];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
if (1 == is_full(board, row, col))
{
return 'Q';
}
return 'C';
}
需要注意的是VS2019中檔案是否添加正確:

三,結果

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/353531.html
標籤:其他
上一篇:【C語言實作游戲】(一)三子棋
