C語言三子棋小游戲的實(shí)現(xiàn)
前言
三子棋又叫九宮棋、圈圈叉叉、一條龍、井字棋等。
三子棋游戲規(guī)則:三子連成一片即為贏,如果雙方都沒有連成線,即為平局。
一、如何實(shí)現(xiàn)?
1.棋盤大小如何確定?
我們要實(shí)現(xiàn)一個3×3的棋盤,就需要定義一個3行3列的數(shù)組,但是數(shù)組的下標(biāo)從0開始,玩家選擇落子坐標(biāo)很不方便,所以要定義一個4×4的數(shù)組,第0行第0列不使用,如下圖紅框內(nèi)的行和列不使用。這樣就方便玩家選擇落子坐標(biāo)。
2.如何判定輸贏?
三子棋的規(guī)則很簡單,只要判斷每一行、每一列、對角線中是否有連成線的,即為贏。
代碼思路:
1、判斷是否有相同的行并且不能為空格(數(shù)組初始化為空格)。
2、判斷是否有相同的列并且不能為空格。
3、判斷主次對角線是否相同并且不能為空格。
4、棋盤下滿后是否為平局。
代碼如下:
//判斷誰贏,'X'表示玩家贏,'0'表示電腦贏,'p'表示平局 char IsWin(char map[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int ret = IsFull(map, ROWS, COLS); //判斷行 for (i = 1; i < row; i++) { if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ') { return map[i][1]; } } //判斷列 for (j = 1; j < col; j++) { if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ') { return map[1][j]; } } //判斷主對角線 if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ') { return map[1][1]; } //判斷次對角線 if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ') { return map[1][3]; } //判斷是否為平局 if (ret == 0) { return 'p'; } else { return ' ';//防止編譯器報錯 } }
注意:
1、三個值比較時不可以使用連等,==是關(guān)系操作符,==是從左到右進(jìn)行運(yùn)算的,計(jì)算表達(dá)式 a == b == c 時,首先會進(jìn)行邏輯運(yùn)算 a == b得出邏輯值1或0,得到的結(jié)果作為返回值,然后進(jìn)行邏輯運(yùn)算 “返回值” == c 得出邏輯值1或0,作為整個表達(dá)式的返回值。所以不能這樣用。
2、判斷完是否平局后,要加一個else,返回一個字符,不然編譯器會報錯:
因?yàn)榫幾g器認(rèn)為還有一種情況:當(dāng)所有的if都不滿足時,沒有返回值,所以要加一個else返回一個對結(jié)果沒有影響的字符。
二、具體代碼實(shí)現(xiàn)
1.頭文件game.h
#include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define ROW 3 #define COL 3 #define ROWS ROW+1 #define COLS COL+1 //初始化棋盤 void InitMap(char map[][COLS], int row, int col); //打印棋盤 void DisplayMap(char map[][COLS], int row, int col); //玩家落子 void PlayerMove(char map[][COLS], int row, int col); //電腦落子 void ComputerMove(char map[][COLS], int row, int col); //判斷棋盤是否滿,0表示滿,1表示未滿 int IsFull(char map[][COLS], int row, int col); //判斷誰贏,'X'表示玩家贏,'0'表示電腦贏,'p'表示平局 char IsWin(char map[][COLS], int row, int col);
2.主函數(shù)main.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void menu() { printf("***********************************************\n"); printf("******** 三子棋 *********\n"); printf("***********************************************\n"); printf("*************** 1.play **************\n"); printf("*************** 0.exit **************\n"); printf("***********************************************\n"); } void game() { char map[ROWS][COLS]; char ret = ' ';//用來接收IsWin()的返回值 InitMap(map, ROWS, COLS);//初始化棋盤 DisplayMap(map, ROWS, COLS);//打印棋盤 do { PlayerMove(map, ROWS, COLS);//玩家落子 ret = IsWin(map, ROWS, COLS); if (ret == 'X') { printf("玩家贏......\n"); break; } else if (ret == 'p') { printf("平局......\n"); break; } ComputerMove(map, ROWS, COLS);//電腦落子 ret = IsWin(map, ROWS, COLS); if (ret == '0') { printf("電腦贏......\n"); break; } }while (IsFull(map,ROWS,COLS));//棋盤已滿,結(jié)束循環(huán) } void test() { int input = 0; srand((unsigned)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() { test(); return 0; }
3.函數(shù)game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" void InitMap(char map[][COLS], int row, int col) { int i = 0; int j = 0; for (i = 1; i < row; i++) { for (j = 1; j < col; j++) { map[i][j] = ' '; } } } void DisplayMap(char map[][COLS], int row, int col) { int i = 0; int j = 0; for (i = 1; i < row; i++) { for (j = 1; j <= col; j++) { printf("%3c",map[i][j]); if (j < col - 1) { printf(" | "); } } printf("\n"); if (i < row - 1) { for (j = 1; j < col; j++) { printf(" --- "); } } printf("\n"); } } void PlayerMove(char map[][COLS], int row, int col) { int x = 0; int y = 0; printf("玩家走->\n"); while (1) { printf("請選擇落子坐標(biāo)->"); scanf("%d %d", &x, &y); if (x >= 1 && x <= 3 && y >= 1 && y <= 3) { if (map[x][y] == ' ') { map[x][y] = 'X'; break;//落子成功就跳出循環(huán) } else { printf("該位置已被占用請重新輸入->\n"); } } else { printf("坐標(biāo)非法,請重新輸入......\n"); } } DisplayMap(map, ROWS, COLS); } void ComputerMove(char map[][COLS], int row, int col) { int x = 0; int y = 0; printf("電腦走->\n"); while (1) { x = rand() % 3 + 1;//1-3 y = rand() % 3 + 1;//1-3 if (map[x][y] == ' ') { map[x][y] = '0'; break; } } DisplayMap(map, ROWS, COLS); } //判斷棋盤是否滿,0表示滿,1表示未滿 int IsFull(char map[][COLS], int row, int col) { int i = 0; int j = 0; int count = 0;//計(jì)算落子過的格子 for (i = 1; i < row; i++) { for (j = 1; j < col; j++) { if (map[i][j] == 'X' || map[i][j] == '0') { count++; } } } if (count == ROW * COL) { return 0;//滿 } else { return 1; } } //判斷誰贏,'X'表示玩家贏,'0'表示電腦贏,'p'表示平局 char IsWin(char map[ROWS][COLS], int row, int col) { int i = 0; int j = 0; int ret = IsFull(map, ROWS, COLS); //判斷行 for (i = 1; i < row; i++) { if (map[i][1] == map[i][2] && map[i][2] == map[i][3] && map[i][1] != ' ') { return map[i][1]; } } //判斷列 for (j = 1; j < col; j++) { if (map[1][j] == map[2][j] && map[2][j] == map[3][j] && map[1][j] != ' ') { return map[1][j]; } } //判斷主對角線 if (map[1][1] == map[2][2] && map[2][2] == map[3][3] && map[1][1] != ' ') { return map[1][1]; } //判斷次對角線 if (map[1][3] == map[2][2] && map[2][2] == map[3][1] && map[1][3] != ' ') { return map[1][3]; } //判斷是否為平局 if (ret == 0) { return 'p'; } else { return ' ';//防止編譯器報錯 } }
4、運(yùn)行結(jié)果示例
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++中double浮點(diǎn)數(shù)精度丟失的深入分析
這篇文章主要給大家介紹了關(guān)于C++中double浮點(diǎn)數(shù)精度丟失的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01delete[] p->elems和free(p->elems)區(qū)別介紹
delete[]和free()都是釋放內(nèi)存的函數(shù),但它們具有不同的使用方法和適用情況,這篇文章主要介紹了delete[] p->elems和free(p->elems)有什么區(qū)別,需要的朋友可以參考下2023-04-04在C++?Qt中實(shí)現(xiàn)異步散列器的代碼示例
在很多工作中,我們需要計(jì)算數(shù)據(jù)或者文件的散列值,例如登錄或下載文件,而在?Qt?中,負(fù)責(zé)這項(xiàng)工作的類為?QCryptographicHash,本文給大家介紹了在C++?Qt中實(shí)現(xiàn)異步散列器的代碼示例,需要的朋友可以參考下2024-09-09