|
Python
Modules pygame and pygwidgets make it possible to use the mouse as input means. (See, for details, I. Kalb, Object-Oriented Python (No Starch Press, 2022))
|
Modula-2
Text window is opened allowing for text menus. A game starts with the key input of 'G'.
|
|
Python
● is Queen and ■ is the goal.
(Left below) Stand-by state before starting. (Right below) PC has won. Clicking 'Restart' leads to stand-by state.
|
Modula-2
o is Queen. (Below) PC has placed Queen at [6,4], waiting for User to input next position.
|
| <Python>
[Main] Main_CornerTheQueen.py
# Corner The Queen, 9-06-2023
... LOOP ...
... PC's move ...
if (state == STATE_QUEEN_1):
if isValid:
iprev = i
jprev = j
i, j = calcPCmove(i, j)
x = coordForCell(i, x0, space)
y = coordForCell(N-1-j, y0, space)
isPCgoal = (i==0) and (j==0)
if isPCgoal:
newText = 'PC has won!'
oTextField.setValue(newText)
chordSound.play()
else:
i = iprev
j = jprev
x = coordForCell(i, x0, space)
y = coordForCell(N-1-j, y0, space)
badSound.play()
state = STATE_QUEEN_2
.......
[Module] CornerTheQueenMove.py
# CornerTheQueenMove
# Based on Oliver Kreylos's program (1999)
from numpy import sqrt
# /************************
# Check if a move is legal:
# ************************/*)
def isMoveLegal(oldi, oldj, newi, newj):
if (oldj == newj): # Horizontal move
legal = (newi>=0) and (newi<oldi)
else:
if (oldi == newi): # Vertical move
legal = (newj>=0) and (newj<oldj)
elif (newi-oldi) == (newj-oldj): # Diagonal move
legal = (newi>=0) and (newj>=0)
and (newi<oldi)
else: # Some other move
legal= False
return legal
#/*************************************************
# Mirror a _Position about the board's main diagonal:
#*************************************************/*)
def mirrorPos(i, j):
ii = j
jj = i
return ii,jj
#*/*************************************************
# Calculate the winning _Position with a given index:
#*************************************************
def calcWinningPos(index):
rindex = index // 2
goldenRatio = 0.5*(sqrt(5.) + 1.)
winj = int(goldenRatio*float(rindex))
wini = winj + rindex
if (index % 2 == 0):
wini,winj = mirrorPos(wini, winj)
return wini,winj
#/*******************************
# Test if two _Positions are equal:
#*******************************/*)
def arePosEqual(i1,j1,i2,j2):
return (i1 == i2) and (j1 == j2)
#/*********************************
# Calculate a very intelligent move:
#*********************************/*)
def calcPCmove(i, j):
isFound = False
index = 0
while (not isFound):
newi,newj = calcWinningPos(index)
if arePosEqual(i, j, newi,newj):
if newi>=newj:
newi -= 1
else:
newj -= 1
isFound = True
else:
if isMoveLegal(i,j,newi,newj):
isFound = True
index += 1
return newi,newj
|
<Modula-2>
[MAIN] CornerTheQueen.MOD
・・・
BEGIN
openTextWin(W1,'Graphic Application');
・・・LOOP・・・
playGame(boardSize);
・・・・・・
[SUB] SubQueenGameK0.MOD
(*/************************
Check if a move is legal:
************************/*)
PROCEDURE isMoveLegal(old, new: _Position): BOOLEAN;
VAR
legal: BOOLEAN;
BEGIN
IF (old.y = new.y) THEN
legal:= (new.x>=0) AND (new.x<old.x);
ELSE
IF (old.x = new.x) THEN
legal:= (new.y>=0) AND (new.y<old.y);
ELSIF (new.x-old.x) = (new.y-old.y) THEN
legal:= (new.x>=0)
AND (new.y>=0) AND (new.x<old.x);
ELSE
legal:= FALSE;
END;
END;
RETURN legal;
END isMoveLegal;
(*/*************************************************
Mirror a _Position about the board's main diagonal:
*************************************************/*)
PROCEDURE mirrorPosition(current: _Position): _Position;
VAR
new: _Position;
BEGIN
new.x:= current.y;
new.y:= current.x;
RETURN new;
END mirrorPosition;
(*/*************************************************
Calculate the winning _Position with a given index:
*************************************************/*)
PROCEDURE calculateWinningPosition
(index: INTEGER): _Position;
VAR
realIndex : INTEGER;
goldenRatio: LONGREAL;
winner : _Position;
BEGIN
realIndex := index DIV 2;
goldenRatio := 0.5*(sqrt(5.0)+1.0);
winner.y := INT(goldenRatio*LFLOAT(realIndex));
winner.x := winner.y + realIndex;
IF (index MOD 2 = 0) THEN
winner:= mirrorPosition(winner);
END;
RETURN winner;
END calculateWinningPosition;
(*/*******************************
Test if two _Positions are equal:
*******************************/*)
PROCEDURE arePositionsEqual
(pos1, pos2: _Position): BOOLEAN;
BEGIN
RETURN (pos1.x = pos2.x)AND(pos1.y = pos2.y);
END arePositionsEqual;
(*/*********************************
Calculate a very intelligent move:
*********************************/*)
PROCEDURE calculateComputerMove
(current: _Position ): _Position;
VAR
new: _Position;
index: INTEGER;
_PositionFound: BOOLEAN;
BEGIN
_PositionFound:= FALSE;
index:= 0;
WHILE (NOT _PositionFound) DO
new:= calculateWinningPosition(index);
IF arePositionsEqual(current,new) THEN
IF (new.x>=new.y) THEN DEC(new.x);
ELSE DEC(new.y);
END;
_PositionFound:= TRUE;
ELSE
IF isMoveLegal(current,new) THEN
_PositionFound:=TRUE;
END;
END;
INC(index);
END;
RETURN new;
END calculateComputerMove;
(*/********************************************
Play the game on a board of the current size:
********************************************/*)
PROCEDURE playGame(boardSize: INTEGER);
VAR
current: _Position;
winningPlayer: INTEGER;
BEGIN
current:= getInitialPosition(boardSize);
winningPlayer:= 1;
WHILE(NOT isLowerLeftCorner(current)) DO
current:= calculateComputerMove(current);
Display(current);
WrStr(" I (computer) moved the queen to Position (");
WrInt(current.x,1); WrStr(',');
WrInt(current.y,1); WrStr(')'); WrLn;
WrLn;
Lib.Delay(1000);
IF (isLowerLeftCorner(current)) THEN
winningPlayer:= 2;
ELSE
WrStr(' Your turn!');
current:= getUserMove(current);
Display(current); Lib.Delay(1500);
END;
END;
WrLn;
IF (winningPlayer=1) THEN
WrStr(" #################"); WrLn;
WrStr(" # You have won! #"); WrLn;
WrStr(" #################"); WrLn;
ELSE
WrStr(" ***************"); WrLn;
WrStr(" * I have won! *"); WrLn;
WrStr(" ***************"); WrLn;
END;
WrLn;
END playGame;
|