Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Johan Gustav Thrane-Nielsen
inf101.v20.sem2.losning
Commits
5cddc8a9
Commit
5cddc8a9
authored
Mar 25, 2020
by
Anna Maria Eilertsen
Browse files
introduced solution code inspired of lab4. Known bug in win condition
parent
c045a1bb
Changes
11
Hide whitespace changes
Inline
Side-by-side
src/main/java/inf101/v20/lab4/grid/Grid.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.grid
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
/**
*
* A Grid contains a set of elements
*
*/
public
class
Grid
<
T
>
implements
IGrid
<
T
>,
Iterable
<
T
>{
private
List
<
T
>
cells
;
private
int
height
;
private
int
width
;
/**
*
* Construct a grid with the given dimensions.
*
* @param width
* @param height
* @param initElement
* What the cells should initially hold (possibly null)
*/
public
Grid
(
int
width
,
int
height
,
T
initElement
)
{
if
(
width
<=
0
||
height
<=
0
)
throw
new
IllegalArgumentException
();
this
.
height
=
height
;
this
.
width
=
width
;
cells
=
new
ArrayList
<>(
height
*
width
);
for
(
int
i
=
0
;
i
<
height
*
width
;
++
i
)
{
cells
.
add
(
initElement
);
}
}
@Override
public
int
getHeight
()
{
return
height
;
// TODO: fyll inn
}
@Override
public
int
getWidth
()
{
return
width
;
// TODO: fyll inn
}
@Override
public
void
set
(
int
x
,
int
y
,
T
elem
)
{
if
(
x
<
0
||
x
>=
width
)
throw
new
IndexOutOfBoundsException
();
if
(
y
<
0
||
y
>=
height
)
throw
new
IndexOutOfBoundsException
();
// TODO: fyll inn
cells
.
set
(
coordinateToIndex
(
x
,
y
),
elem
);
}
private
int
coordinateToIndex
(
int
x
,
int
y
)
{
return
x
+
y
*
width
;
}
@Override
public
T
get
(
int
x
,
int
y
)
{
if
(
x
<
0
||
x
>=
width
)
throw
new
IndexOutOfBoundsException
();
if
(
y
<
0
||
y
>=
height
)
throw
new
IndexOutOfBoundsException
();
return
cells
.
get
(
coordinateToIndex
(
x
,
y
));
// TODO: fyll inn
}
@Override
public
IGrid
<
T
>
copy
()
{
Grid
<
T
>
newGrid
=
new
Grid
<>(
getWidth
(),
getHeight
(),
null
);
for
(
int
x
=
0
;
x
<
width
;
x
++)
for
(
int
y
=
0
;
y
<
height
;
y
++)
newGrid
.
set
(
x
,
y
,
get
(
x
,
y
));
return
newGrid
;
}
@Override
public
Iterator
<
T
>
iterator
()
{
return
cells
.
iterator
();
}
}
src/main/java/inf101/v20/lab4/grid/IGrid.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.grid
;
/**
* IGrid is a generic grid
*
* @author Anna Eilertsen - anna.eilertsen@uib.no
*
*/
public
interface
IGrid
<
T
>
{
/**
* @return The height of the grid.
*/
int
getHeight
();
/**
* @return The width of the grid.
*/
int
getWidth
();
/**
*
* Set the contents of the cell in the given x,y location.
*
* y must be greater than or equal to 0 and less than getHeight().
* x must be greater than or equal to 0 and less than getWidth().
*
* @param x The column of the cell to change the contents of.
* @param y The row of the cell to change the contents of.
* @param element The contents the cell is to have.
*/
void
set
(
int
x
,
int
y
,
T
element
);
/**
*
* Get the contents of the cell in the given x,y location.
*
* y must be greater than or equal to 0 and less than getHeight().
* x must be greater than or equal to 0 and less than getWidth().
*
* @param x The column of the cell to get the contents of.
* @param y The row of the cell to get contents of.
*/
T
get
(
int
x
,
int
y
);
/**
* Make a copy
*
* @return A shallow copy of the grid, with the same elements
*/
IGrid
<
T
>
copy
();
}
\ No newline at end of file
src/main/java/inf101/v20/lab4/mnkgames/ConnectFour.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.mnkgames
;
public
class
ConnectFour
extends
MNKGame
{
ConnectFour
()
{
super
(
7
,
6
,
4
);
}
@Override
public
void
putPieceAt
(
int
x
,
int
y
)
{
putPieceAt
(
x
);
}
/**
* Special rules for the Connect Four
*
* Players can only drop pieces into column, they cannot decide which
* row they should land in.
*
* Pieces will stop at the first available row
*
* @param x the column to which the piece is added
*/
public
void
putPieceAt
(
int
x
)
{
assert
x
>=
0
&&
x
<
getWidth
();
int
firstAvailableRow
=
-
1
;
for
(
int
y
=
0
;
y
<
getHeight
();
y
++,
firstAvailableRow
=
y
-
1
)
{
if
(
getPieceAt
(
x
,
y
)
!=
Piece
.
NONE
)
{
break
;
}
}
//precondition check
if
(
firstAvailableRow
==
-
1
)
throw
new
IllegalStateException
(
"There were no available spots in column "
+
x
);
//add the current piece
super
.
putPieceAt
(
x
,
firstAvailableRow
);
}
}
\ No newline at end of file
src/main/java/inf101/v20/lab4/mnkgames/GUIMain.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.mnkgames
;
public
class
GUIMain
{
public
static
void
main
(
String
[]
args
)
{
MNKGameGUI
.
run
(()
->
new
ConnectFour
());
// MNKGameGUI.run(() -> new TicTacToe());
}
}
src/main/java/inf101/v20/lab4/mnkgames/MNKGame.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.mnkgames
;
import
inf101.v20.lab4.grid.Grid
;
public
abstract
class
MNKGame
{
private
int
width
;
private
int
height
;
private
int
k
;
private
Grid
<
Piece
>
grid
;
private
Piece
currentPlayer
;
enum
Piece
{
NONE
,
BLACK
,
WHITE
;
public
Piece
next
()
{
return
this
==
Piece
.
BLACK
?
Piece
.
WHITE
:
Piece
.
BLACK
;
}
}
/**
*
* @param m width: dimensions along x-axis
* @param n height: dimensions along y-axis
* @param k row length win condition
*/
MNKGame
(
int
m
,
int
n
,
int
k
){
width
=
m
;
height
=
n
;
this
.
k
=
k
;
grid
=
new
Grid
<
MNKGame
.
Piece
>(
width
,
height
,
Piece
.
NONE
);
currentPlayer
=
Piece
.
BLACK
;
}
public
int
getWidth
()
{
return
width
;
}
public
int
getHeight
()
{
return
height
;
}
public
int
getRowsToWin
()
{
return
k
;
}
public
Piece
getPieceAt
(
int
x
,
int
y
)
{
if
(
x
>=
width
||
x
<
0
||
y
>=
height
||
y
<
0
)
throw
new
IllegalArgumentException
(
"Invalid coordinate"
);
return
grid
.
get
(
x
,
y
);
}
/**
* Add a piece belonging to the current player to position (x, y)
*
* @param x the x-coordinate such that 0 <= x < width
* @param y the y-coordinate such that 0 <= y < height
*/
public
void
putPieceAt
(
int
x
,
int
y
)
{
if
(
x
>=
width
||
x
<
0
||
y
>=
height
||
y
<
0
)
throw
new
IllegalArgumentException
(
"Cannot add a piece to this position"
);
if
(
grid
.
get
(
x
,
y
)
!=
Piece
.
NONE
)
throw
new
IllegalArgumentException
(
"Position is already filled"
);
grid
.
set
(
x
,
y
,
currentPlayer
);
currentPlayer
=
currentPlayer
.
next
();
}
public
boolean
hasWinner
()
{
return
getWinner
()!=
Piece
.
NONE
;
}
public
Piece
getWinner
()
{
for
(
int
x
=
0
;
x
<
width
;
x
++)
{
for
(
int
y
=
0
;
y
<
height
;
y
++)
{
int
count
=
0
;
Piece
current
=
grid
.
get
(
x
,
y
);
if
(
current
==
Piece
.
NONE
)
continue
;
//horizontal
for
(
int
i
=
x
-
k
+
1
;
i
<=
x
+
k
-
1
;
i
++)
{
System
.
out
.
println
(
"Looking at \n"
+
debugToString
(
i
,
y
));
if
(
i
<
0
||
i
>=
getWidth
())
continue
;
if
(
grid
.
get
(
i
,
y
)
!=
current
)
{
count
=
0
;
}
else
{
count
++;
}
if
(
count
==
k
)
return
current
;
}
count
=
0
;
//vertical
for
(
int
j
=
y
-
k
+
1
;
j
>=
0
&&
j
<=
y
+
k
-
1
;
j
++)
{
System
.
out
.
println
(
"Looking at \n"
+
debugToString
(
x
,
j
));
if
(
j
<
0
||
j
>=
getHeight
())
continue
;
if
(
grid
.
get
(
x
,
j
)
!=
current
)
{
count
=
0
;
}
else
{
count
++;
}
if
(
count
==
k
)
return
current
;
}
count
=
0
;
//diagonal (0,0) -> (l, l) where l := min(m, n)
for
(
int
i
=
x
-
k
+
1
,
j
=
y
-
k
+
1
;
i
<=
x
+
k
-
1
&&
j
<=
y
+
k
-
1
;
i
++,
j
++)
{
System
.
out
.
println
(
"Looking at \n"
+
debugToString
(
i
,
j
));
if
(
i
<
0
||
j
<
0
||
i
>=
getWidth
()
||
j
>=
getHeight
())
continue
;
if
(
grid
.
get
(
i
,
j
)
!=
current
)
{
count
=
0
;
}
else
{
count
++;
}
if
(
count
==
k
)
return
current
;
}
//diagonal (0,n) -> (m, 0) where l := min(m, n)
for
(
int
i
=
x
+
k
-
1
,
j
=
y
-
k
+
1
;
i
>=
x
-
k
+
1
&&
j
<=
y
+
k
-
1
;
i
--,
j
++)
{
System
.
out
.
println
(
"Looking at \n"
+
debugToString
(
i
,
j
));
if
(
i
<
0
||
j
<
0
||
i
>=
getWidth
()
||
j
>=
getHeight
())
continue
;
if
(
grid
.
get
(
i
,
j
)
!=
current
)
{
count
=
0
;
}
else
{
count
++;
}
if
(
count
==
k
)
return
current
;
}
}
}
return
Piece
.
NONE
;
}
@Override
public
String
toString
()
{
String
r
=
""
;
for
(
int
j
=
0
;
j
<
height
;
j
++)
{
for
(
int
i
=
0
;
i
<
width
;
i
++)
{
r
+=
" "
+
getPieceAt
(
i
,
j
).
name
().
charAt
(
0
);
}
r
+=
"\n"
;
}
return
r
;
}
public
String
debugToString
(
int
x
,
int
y
)
{
String
r
=
""
;
for
(
int
j
=
0
;
j
<
height
;
j
++)
{
for
(
int
i
=
0
;
i
<
width
;
i
++)
{
if
(
i
==
x
&&
j
==
y
)
{
r
+=
" "
+
"X"
;
continue
;
}
r
+=
" "
+
getPieceAt
(
i
,
j
).
name
().
charAt
(
0
);
}
r
+=
"\n"
;
}
return
r
;
}
}
src/main/java/inf101/v20/lab4/mnkgames/MNKGameComponent.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.mnkgames
;
import
java.awt.Color
;
import
java.awt.Component
;
import
java.awt.Graphics
;
import
inf101.v20.lab4.mnkgames.MNKGame.Piece
;
public
class
MNKGameComponent
extends
Component
{
private
static
final
long
serialVersionUID
=
4548104480314044678L
;
private
MNKGame
game
;
/**
* The height of each cell in pixels.
*/
private
final
int
cellHeight
=
20
;
/**
* The width of each cell in pixels.
*/
private
final
int
cellWidth
=
20
;
/**
* The size of the space between each cell and between the cell and the edge
* of the window.
*/
private
final
int
padding
=
1
;
public
MNKGameComponent
(
MNKGame
game
){
this
.
game
=
game
;
}
/*
* (non-Javadoc)
*
* @see java.awt.Component#paint(java.awt.Graphics) Paints the labyrinth.
*/
@Override
public
void
paint
(
Graphics
g
)
{
for
(
int
x
=
0
;
x
<
game
.
getWidth
();
x
++)
{
for
(
int
y
=
0
;
y
<
game
.
getHeight
();
y
++)
{
g
.
setColor
(
getColor
(
game
.
getPieceAt
(
x
,
y
)));
g
.
fillRect
(
x
*
(
cellHeight
+
padding
)
+
padding
,
//
getHeight
()
-
(
y
*
(
cellHeight
+
padding
)
+
padding
)
-
cellHeight
,
//
cellHeight
,
cellWidth
);
}
}
}
/**
* TODO duplicated in MNKGameGUI
*
* Maps from Piece values to colors
*
* NB: White maps to red RN
*
* @param pieceAt
* @return
*/
protected
Color
getColor
(
Piece
pieceAt
)
{
switch
(
pieceAt
)
{
case
BLACK
:
return
Color
.
BLACK
;
case
WHITE
:
return
Color
.
RED
;
default
:
return
Color
.
WHITE
;
}
}
}
\ No newline at end of file
src/main/java/inf101/v20/lab4/mnkgames/MNKGameGUI.java
0 → 100644
View file @
5cddc8a9
package
inf101.v20.lab4.mnkgames
;
import
java.awt.BorderLayout
;
import
java.awt.Color
;
import
java.awt.Dimension
;
import
java.awt.GridLayout
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.ActionListener
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
java.awt.event.MouseListener
;
import
java.util.function.Supplier
;
import
javax.swing.BorderFactory
;
import
javax.swing.JButton
;
import
javax.swing.JFrame
;
import
javax.swing.JLabel
;
import
javax.swing.JPanel
;
import
inf101.v20.lab4.grid.Grid
;
import
inf101.v20.lab4.mnkgames.MNKGame.Piece
;
/**
*
* @author Anna Eilertsen
*/
public
class
MNKGameGUI
extends
JPanel
implements
ActionListener
{
private
static
final
long
serialVersionUID
=
8755882090377973497L
;
/**
*
* Initializes a JFrame in which we place the a CellAutomataGUI containing
* the given ILabyrinth.
*
* @param ca
*/
public
static
void
run
(
Supplier
<
MNKGame
>
gameSupplier
)
{
JFrame
f
=
new
JFrame
(
"mnkGame"
);
f
.
setDefaultCloseOperation
(
JFrame
.
EXIT_ON_CLOSE
);
MNKGameGUI
ap
=
new
MNKGameGUI
(
gameSupplier
);
ap
.
initialize
();
f
.
add
(
"Center"
,
ap
);
f
.
pack
();
f
.
setVisible
(
true
);
}
MNKGame
game
;
private
JButton
setBoardButton
;
private
JLabel
message
;
private
Grid
<
GamePanel
>
grid
;
private
Supplier
<
MNKGame
>
gameSupplier
;
public
MNKGameGUI
(
Supplier
<
MNKGame
>
gameSupplier
)
{
this
.
gameSupplier
=
gameSupplier
;
this
.
game
=
gameSupplier
.
get
();
this
.
grid
=
new
Grid
<
GamePanel
>(
game
.
getWidth
(),
game
.
getHeight
(),
null
);
}
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*
* Called whenever a button is pressed or the timer tells us its time to
* make a step.
*/
@Override
public
void
actionPerformed
(
ActionEvent
e
)
{
if
(
e
.
getSource
()
==
setBoardButton
)
{
reset
();
}
}
private
void
reset
()
{
game
=
gameSupplier
.
get
();
updateMessage
();
this
.
updateUI
();
removeAll
();
initialize
();
}
private
void
updateBoardUI
()
{
grid
.
forEach
(
item
->
item
.
updateToGame
());
MNKGameGUI
.
super
.
updateUI
();
if
(
game
.
hasWinner
())
{
System
.
out
.
println
(
"Winner!"
);
stop
();
}
}
private
void
stop
()
{
updateMessage
();
grid
.
forEach
(
item
->
item
.
removeMouseListeners
());
}
//Class that defines what happens (i.e: the color changes) when a panel is clicked
class
BoxListener
extends
MouseAdapter
{
public
void
mousePressed
(
MouseEvent
me
){
GamePanel
clickedPanel
=(
GamePanel
)
me
.
getSource
();
// get the reference to the box that was clicked
clickedPanel
.
click
();
}
}
/**
* Maps from Piece values to colors
*
* NB: White maps to red RN
*
* @param pieceAt
* @return
*/
protected
Color
getColor
(
Piece
pieceAt
)
{
switch
(
pieceAt
)
{
case
BLACK
:
return
Color
.
getHSBColor
(
90
,
65
,
20.3f
);
case
WHITE
:
return
Color
.
getHSBColor
(
308
,
26
,
34
);
default
:
return
Color
.
WHITE
;
}
}
public
Dimension
getPreferredSize
()
{
return
new
Dimension
(
100
*
game
.
getHeight
(),
100
*
game
.
getWidth
());
}
private
class
GamePanel
extends
JPanel
{
private
int
x
,
y
;
private
static
final
long
serialVersionUID
=
1L
;
public
GamePanel
(
int
x
,
int
y
)
{
this
.
x
=
x
;
this
.
y
=
y
;
}
public
void
removeMouseListeners
()
{
MouseListener
[]
mouseListeners
=
getMouseListeners
();
for
(
int
i
=
0
;
i
<
mouseListeners
.
length
;
i
++)
{
this
.
removeMouseListener
(
mouseListeners
[
i
]);
}
}
private
void
updateToGame
()
{
setBackground
(
getColor
(
game
.
getPieceAt
(
x
,
y
)));
if
(
filled
())
{
makeUnClickable
();
}
}
private
void
makeUnClickable
()
{
removeMouseListeners
();