📄 gomoku.c
字号:
int Random(x)int x;{ return((rand() / 19) % x);}/* Adds one to the number of pieces in a line */void Add(Num)int *Num;{ /* Adds one to the number. */ *Num = *Num + 1; /* If it is the first piece in the line, then the opponent cannot use * it any more. */ if (*Num == 1) TotalLines = TotalLines - 1; /* The game is won if there are 5 in line. */ if (*Num == 5) GameWon = TRUE;}/* Updates the value of a square for each player, taking into account that player has placed an extra piece in the square. The value of a square in a usable line is Weight[Lin[Player]+1] where Lin[Player] is the number of pieces already placedin the line */void Update(Lin, Valu, Opponent)int Lin[];int Valu[];int Opponent;{ /* If the opponent has no pieces in the line, then simply update the * value for player */ if (Lin[Opponent] == 0) Valu[Player] += Weight[Lin[Player] + 1] - Weight[Lin[Player]]; else /* If it is the first piece in the line, then the line is * spoiled for the opponent */ if (Lin[Player] == 1) Valu[Opponent] -= Weight[Lin[Opponent] + 1];}/* Performs the move X,Y for player, and updates the global variables(Board, Line, Value, Player, GameWon, TotalLines and the screen) */void MakeMove(X, Y)int X, Y;{ int Opponent; int X1, Y1; int K, L, WinningLine; WinningLine = Null; Opponent = OpponentColor(Player); GameWon = FALSE; /* Each square of the board is part of 20 different lines. The adds * one to the number of pieces in each of these lines. Then it * updates the value for each of the 5 squares in each of the 20 * lines. Finally Board is updated, and the move is printed on the * screen. */ /* Horizontal lines, from left to right */ for (K = 0; K <= 4; K++) { X1 = X - K; /* Calculate starting point */ Y1 = Y; if ((1 <= X1) && (X1 <= SIZE - 4)) { /* Check starting point */ Add(&Line[0][X1][Y1][Player]); /* Add one to line */ if (GameWon && (WinningLine == Null)) /* Save winning line */ WinningLine = Horiz; for (L = 0; L <= 4; L++) /* Update value for the * 5 squares in the line */ Update(Line[0][X1][Y1], Value[X1 + L][Y1], Opponent); } } for (K = 0; K <= 4; K++) { /* Diagonal lines, from lower left to * upper right */ X1 = X - K; Y1 = Y - K; if ((1 <= X1) && (X1 <= SIZE - 4) && (1 <= Y1) && (Y1 <= SIZE - 4)) { Add(&Line[1][X1][Y1][Player]); if (GameWon && (WinningLine == Null)) /* Save winning line */ WinningLine = DownLeft; for (L = 0; L <= 4; L++) Update(Line[1][X1][Y1], Value[X1 + L][Y1 + L], Opponent); } } /* for */ for (K = 0; K <= 4; K++) { /* Diagonal lines, down right to upper left */ X1 = X + K; Y1 = Y - K; if ((5 <= X1) && (X1 <= SIZE) && (1 <= Y1) && (Y1 <= SIZE - 4)) { Add(&Line[3][X1][Y1][Player]); if (GameWon && (WinningLine == Null)) /* Save winning line */ WinningLine = DownRight; for (L = 0; L <= 4; L++) Update(Line[3][X1][Y1], Value[X1 - L][Y1 + L], Opponent); } } /* for */ for (K = 0; K <= 4; K++) { /* Vertical lines, from down to up */ X1 = X; Y1 = Y - K; if ((1 <= Y1) && (Y1 <= SIZE - 4)) { Add(&Line[2][X1][Y1][Player]); if (GameWon && (WinningLine == Null)) /* Save winning line */ WinningLine = Vert; for (L = 0; L <= 4; L++) Update(Line[2][X1][Y1], Value[X1][Y1 + L], Opponent); } } Board[X][Y] = Player; /* Place piece in board */ if (GameWon) BlinkWinner(Player, X, Y, WinningLine); else PrintMove(Player, X, Y);/* Print move on screen */ Player = Opponent; /* The opponent is next to move */}int GameOver()/* A game is over if one of the players havewon, or if there are no more Empty lines */{ return(GameWon || (TotalLines <= 0));}/* Finds a move X,Y for player, simply by picking the one with thehighest value */void FindMove(X, Y)int *X, *Y;{ int Opponent; int I, J; int Max, Valu; Opponent = OpponentColor(Player); Max = -10000; /* If no square has a high value then pick the one in the middle */ *X = (SIZE + 1) / 2; *Y = (SIZE + 1) / 2; if (Board[*X][*Y] == Empty) Max = 4; /* The evaluation for a square is simply the value of the square for * the player (attack points) plus the value for the opponent * (defense points). Attack is more important than defense, since it * is better to get 5 in line yourself than to prevent the op- ponent * from getting it. */ /* For all Empty squares */ for (I = 1; I <= SIZE; I++) for (J = 1; J <= SIZE; J++) if (Board[I][J] == Empty) { /* Calculate evaluation */ Valu = Value[I][J][Player] * (16 + AttackFactor) / 16 + Value[I][J][Opponent] + Random(4); /* Pick move with highest value */ if (Valu > Max) { *X = I; *Y = J; Max = Valu; } }}char GetChar()/* Get a character from the keyboard */{ int c; c = getch(); if (c < 0) abort(); if (c == '\033') { /* arrow key */ if ((c = getch()) == '[') { c = getch(); switch (c) { case 'A': c = 'U'; break; case 'B': c = 'D'; break; case 'C': c = 'R'; break; case 'D': c = 'L'; break; default: c = '?'; break; } } else c = '?'; } if (islower(c)) return toupper(c); else return c;}/* Reads in a valid command character */void ReadCommand(X, Y, Command)int X, Y;char *Command;{ int ValidCommand; do { ValidCommand = TRUE; GotoSquare(X, Y); /* Goto square */ refresh(); *Command = GetChar(); /* Read from keyboard */ switch (*Command) { case '\n': /* '\n', '\r' or space means place a */ case '\r': case ' ': *Command = 'E'; break; /* stone at the cursor position */ case 'L': case 'R': case 'U': case 'D': case '7': case '9': case '1': case '3': case 'N': case 'Q': case 'A': case 'P': case 'H': break; case '8': *Command = 'U'; break; case '2': *Command = 'D'; break; case '4': *Command = 'L'; break; case '6': *Command = 'R'; break; default: { if (GameOver()) *Command = 'P'; else ValidCommand = FALSE; break; } } } while (!ValidCommand);}void InterpretCommand(Command)char Command;{ int Temp; switch (Command) { case 'N':{ /* Start new game */ ResetGame(FALSE); /* ResetGame but only redraw * the board */ X = (SIZE + 1) / 2; Y = X; break; } case 'H': FindMove(&X, &Y); break; /* Give the user a hint */ case 'L': X = (X + SIZE - 2) % SIZE + 1; break; /* Left */ case 'R': X = X % SIZE + 1; break; /* Right */ case 'D': Y = (Y + SIZE - 2) % SIZE + 1; break; /* Down */ case 'U': Y = Y % SIZE + 1; break; /* Up */ case '7':{ if ((X == 1) || (Y == SIZE)) { /* Move diagonally *//* t * owards upper left */ Temp = X; X = Y; Y = Temp; } else { X = X - 1; Y = Y + 1; } break; } case '9':{ /* Move diagonally */ if (X == SIZE) {/* toward upper right */ X = (SIZE - Y) + 1; Y = 1; } else if (Y == SIZE) { Y = (SIZE - X) + 1; X = 1; } else { X = X + 1; Y = Y + 1; } break; } case '1':{ /* Move diagonally */ if (Y == 1) { /* toward lower left */ Y = (SIZE - X) + 1; X = SIZE; } else if (X == 1) { X = (SIZE - Y) + 1; Y = SIZE; } else { X = X - 1; Y = Y - 1; } break; } case '3':{ /* Move diagonally */ if ((X == SIZE) || (Y == 1)) { /* toward lower right */ Temp = X; X = Y; Y = Temp; } else { X = X + 1; Y = Y - 1; } break; } case 'A': AutoPlay = TRUE; break; /* Auto play mode */ } /* case */} /* InterpretCommand */void PlayerMove()/* Enter and make a move */{ if (Board[X][Y] == Empty) { MakeMove(X, Y); if (GameWon) PrintMsg("Congratulations, You won!"); Command = 'P'; } refresh();} /* PlayerMove */void ProgramMove()/* Find and perform programs move */{ do { if (GameOver()) { AutoPlay = FALSE; if ((Command != 'Q') && (!GameWon)) PrintMsg("Tie game!"); } else { FindMove(&X, &Y); MakeMove(X, Y); if (GameWon) PrintMsg("I won!"); } refresh(); } while (AutoPlay);}int main(){ Initialize(); ResetGame(TRUE); /* ResetGame and draw the entire screen */ refresh(); X = (SIZE + 1) / 2; /* Set starting position to */ Y = X; /* the middle of the board */ do { ReadCommand(X, Y, &Command); if (GameOver()) if (Command != 'Q') Command = 'N'; InterpretCommand(Command); if (Command == 'E') PlayerMove(); if (Command == 'P' || Command == 'A') ProgramMove(); } while (Command != 'Q'); Abort("Good bye!"); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -