package game;
import player.AbstractPlayer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class Game {
/*
* COLORS:
* GREEN
* RED
* YELLOW
* WHITE
* BLUE
* (COLORED)
*/
final static int GREEN = 0;
final static int RED = 1;
final static int YELLOW = 2;
final static int WHITE = 3;
final static int BLUE = 4;
final static int COLORS = 5;
final static int NR_PLAYERS = 2;
static int CARDS_PER_PLAYER;
final static int NR_OF_CARDS = 50;
static int CARDS_IN_DECK;
final static int MAX_HINTS = 8;
final static int MAX_THUNDERS = 3;
int hints;
int thunders;
static ArrayList<Card> cards;
static Card[][] deck;
static int[] deckCounter;
static ArrayList<Card> trash;
static AbstractPlayer[] players;
static int currentPlayer;
static int selectedPlayer;
static int selectedCards;
static int chosenColor;
static int chosenValue;
static boolean useColor;
static boolean useValue;
static boolean placeCard;
static boolean trashCard;
static boolean won;
static boolean lost;
//UI STUFF
JFrame mainFrame;
JPanel gamePanel;
JPanel hintPanel;
JPanel thunderPanel;
JPanel buttonPanel;
JPanel deckPanel;
JLabel[][] deckUI;
JButton colorButton;
JButton valueButton;
JButton nextMove;
JButton placeCardButton;
JButton trashCardButton;
JLabel[] hintUI;
JLabel[] thunderUI;
static JPanel[] playersUI;
public static void main(String[] args) {
/*Game game = */new Game();
System.out.println("Player " + currentPlayer + "'s turn");
}
public Game(){
init();
}
private void init(){
CARDS_PER_PLAYER = (NR_PLAYERS < 3) ? 5 : 4;
hints = MAX_HINTS;
thunders = 0;
createPlayers();
currentPlayer = 0;
resetMoveValues();
addCards();
CARDS_IN_DECK = cards.size();
createUI();
dealCards();
}
private void resetMoveValues(){
selectedPlayer = -1;
chosenColor = -1;
chosenValue = -1;
selectedCards = 0;
useColor = useValue = trashCard = placeCard = false;
}
private void createPlayers(){
players = new AbstractPlayer[NR_PLAYERS];
playersUI = new JPanel[NR_PLAYERS];
for(int i=0; i<NR_PLAYERS; ++i){
players[i] = new SwingPlayer(CARDS_PER_PLAYER);
playersUI[i] = new JPanel();
}
players[0].print();
}
private void addCards(){
cards = new ArrayList<Card>();
deck = new Card[COLORS][5];
deckCounter = new int[5];
trash = new ArrayList<Card>();
int[] dist = new int[]{3, 2, 2, 2, 1};
int[][] tmp_cards = new int[][]{
dist.clone(),
dist.clone(),
dist.clone(),
dist.clone(),
dist.clone()
};
for(int i=0; i<NR_OF_CARDS; ++i){
Point p = null;
do{
p = randomPosition();
} while(tmp_cards[p.x][p.y] == 0);
tmp_cards[p.x][p.y]--;
cards.add(new Card(p.x, (p.y + 1)));
}
}
private boolean checkValidMove(){
if(selectedCards == 0) return false;
if(!hintAvailable() && (useColor || useValue)) return false;
if((trashCard || placeCard) && selectedCards == 1) return true;
int countCards = 0;
for(int i=0; i<CARDS_PER_PLAYER; ++i){
AbstractPlayer p = players[selectedPlayer];
if(useColor){
if(p.getCard(i).getColorInt() == chosenColor) countCards++;
} else if(useValue){
if(p.getCard(i).getValue() == chosenValue) countCards++;
}
}
return (countCards == selectedCards);
}
private void createUI(){
mainFrame = new JFrame("Hanabi");
mainFrame.setSize(1000, 1000);
mainFrame.setLocation(0, 0);
mainFrame.setLayout(new BorderLayout());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.getContentPane().setBackground(Color.black);
mainFrame.setVisible(true);
gamePanel = new JPanel();
gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.Y_AXIS));
GridLayout deckLayout = new GridLayout(COLORS, 5);
deckPanel = new JPanel(deckLayout);
deckPanel.setBackground(Color.black);
deckUI = new JLabel[COLORS][5];
for(int i=0; i<COLORS; ++i){
for(int j=0; j<5; ++j){
JLabel tmp = new JLabel("Not set");
tmp.setBackground(Color.black);
tmp.setForeground(Color.white);
deckUI[i][j] = tmp;
deckPanel.add(deckUI[i][j]);
}
}
hintPanel = new JPanel();
thunderPanel = new JPanel();
buttonPanel = new JPanel();
colorButton = new JButton("Color");
valueButton = new JButton("Value");
nextMove = new JButton("Next");
placeCardButton = new JButton("Place");
trashCardButton = new JButton("Trash");
buttonPanel.add(colorButton);
buttonPanel.add(valueButton);
buttonPanel.add(nextMove);
buttonPanel.add(placeCardButton);
buttonPanel.add(trashCardButton);
mainFrame.add(gamePanel, BorderLayout.CENTER);
gamePanel.add(hintPanel);
gamePanel.add(thunderPanel);
gamePanel.add(buttonPanel);
gamePanel.add(deckPanel);
hintUI = new JLabel[MAX_HINTS];
for(int i=0; i<MAX_HINTS; ++i){
JLabel tmp = new JLabel();
tmp.setText("1");
tmp.setBackground(Color.white);
tmp.setName("Hint_" + i);
hintPanel.add(tmp);
hintUI[i] = tmp;
}
thunderUI = new JLabel[MAX_THUNDERS];
for(int i=0;i<MAX_THUNDERS; ++i){
JLabel tmp = new JLabel();
tmp.setText("0");
tmp.setBackground(Color.cyan);
tmp.setName("Thunder_" + i);
thunderPanel.add(tmp);
thunderUI[i] = tmp;
}
colorButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(!hintAvailable()){
System.out.println("No hints left!");
return;
}
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useColor = true;
useValue = false;
placeCard = false;
trashCard = false;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
valueButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(!hintAvailable()){
System.out.println("No hints left!");
return;
}
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useValue = true;
useColor = false;
placeCard = false;
trashCard = false;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
nextMove.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(!checkValidMove()){
System.out.println("Please select all cards of the selected color/value");
return;
}
int selCardIndex = 0;
for(int i=0; i<CARDS_PER_PLAYER; ++i){
SwingPlayer sp = (SwingPlayer) players[selectedPlayer];
JLabel card = sp.getUiCard(i);
if(card.getBackground() == Color.pink){
selCardIndex = i;
card.setBackground(Color.black);
if(useColor){
String color = intColorToText(chosenColor);
sp.setCardInfo(i, sp.getCardInfo(i) + ", " + color);
} else if(useValue){
String value = "is " + chosenValue;
sp.setCardInfo(i, sp.getCardInfo(i) + ", " + value);
}
} else {
if(useColor){
String color = "not " + intColorToText(chosenColor);
sp.setCardInfo(i, sp.getCardInfo(i) + ", " + color);
} else if(useValue){
String value = "is not " + chosenValue;
sp.setCardInfo(i, sp.getCardInfo(i) + ", " + value);
}
}
}
if(useColor || useValue){
hintUI[hints-1].setText("0");
hints--;
} else if(trashCard){
moveCardToTrash(selCardIndex);
if(hints != MAX_HINTS){
hintUI[hints].setText("1");
hints++;
if(hints > MAX_HINTS) hints = MAX_HINTS;
}
} else if(placeCard){
Card c = players[currentPlayer].getCard(selCardIndex);
int color = c.getColorInt();
int value = c.getValue();
int deckValue = deckCounter[color] + 1;
if(deckValue == value){ //place card possible
deckCounter[color]++;
deck[color][value-1] = c;
deckUI[color][value-1].setText("Value: " + value);
deckUI[color][value-1].setForeground(c.getColor());
setWonOrLost();
} else { //card too high or too low
thunderUI[thunders++].setText("1");
moveCardToTrash(selCardIndex);
setWonOrLost();
if(lost) return;
}
dealCard(selCardIndex, currentPlayer);
updateCards(selCardIndex);
}
System.out.println("Player " + currentPlayer + " has finished his move!");
currentPlayer++;
if(currentPlayer == NR_PLAYERS) currentPlayer = 0;
resetMoveValues();
System.out.println(CARDS_IN_DECK + " cards left.");
System.out.println(trash.size() + " cards in trash");
System.out.println("Player " + currentPlayer + "'s turn");
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
trashCardButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useColor = false;
useValue = false;
placeCard = false;
trashCard = true;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
placeCardButton.addMouseListener(new MouseListener(){
@Override
public void mouseReleased(MouseEvent e) {
if(selectedCards > 0){
System.out.println("Please deselect all cards first");
return;
}
useColor = false;
useValue = false;
trashCard = false;
placeCard = true;
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
}
private void moveCardToTrash(int index){
trash.add(players[currentPlayer].getCard(index));
updateCards(index);
}
private void updateCards(int index){
dealCard(index, currentPlayer);
players[currentPlayer].setCardInfo(index, "");
Card c = players[currentPlayer].getCard(index);
JLabel card = ((SwingPlayer) players[currentPlayer]).getUiCard(index);
if(c.getValue() == -1){ //dummy card, no more cards
card.setForeground(Color.orange);
card.setText("No Cards left");
MouseListener[] listeners = card.getMouseListeners();
for(int i=0; i<listeners.length; ++i){
card.removeMouseListener(listeners[i]);
}
}
}
private void dealCard(int cardID, int playerID){
Card card;
if(CARDS_IN_DECK > 0){
int index = random(CARDS_IN_DECK--);
card = cards.remove(index);
} else {
card = new Card(3, -1);
}
players[playerID].setCard(cardID, card);
}
private void dealCards(){
int dealtCards = 0;
for(; dealtCards < CARDS_PER_PLAYER; ++dealtCards){
for(int i=0; i<NR_PLAYERS; ++i){
int index = random(CARDS_IN_DECK--);
Card card = cards.remove(index);
players[i].setCard(dealtCards, card);
}
}
/*
* PLAYER 0: SOUTH
* PLAYER 1: EAST
* PLAYER 2: NORTH
* PLAYER 3: WEST
*/
for(int i=0; i<NR_PLAYERS; ++i){
JPanel playerContainer = ((SwingPlayer) players[i]).getContainer();
BoxLayout containerLayout = null;
String playerSide = null;
switch(i){
case 0:
playerSide = BorderLayout.SOUTH;
containerLayout = new BoxLayout(playerContainer, BoxLayout.X_AXIS);
break;
case 1:
playerSide = BorderLayout.EAST;
containerLayout = new BoxLayout(playerContainer, BoxLayout.Y_AXIS);
break;
case 2:
playerSide = BorderLayout.NORTH;
containerLayout = new BoxLayout(playerContainer, BoxLayout.X_AXIS);
break;
case 3:
playerSide = BorderLayout.WEST;
containerLayout = new BoxLayout(playerContainer, BoxLayout.Y_AXIS);
break;
}
playerContainer.setLayout(containerLayout);
playerContainer.setBackground(Color.black);
for(int j=0; j<CARDS_PER_PLAYER; ++j){
JLabel curr = ((SwingPlayer) players[i]).getUiCard(j);
curr.setName(i + "_card" + j);
curr.setHorizontalAlignment(SwingConstants.CENTER);
curr.setSize(50, 50);
Font f = curr.getFont();
curr.setFont(new Font(f.getFontName(), f.getStyle(), f.getSize()*2));
curr.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
JLabel label = (JLabel) e.getComponent();
String name = label.getName();
int clickedPlayer = Integer.parseInt(name.substring(0, 1));
int clickedCard = Integer.parseInt(name.substring(name.length()-1));
Card card = players[clickedPlayer].getCard(clickedCard);
int clickedValue = card.getValue();
int clickedColor = card.getColorInt();
if(label.getBackground() == Color.pink){
selectedCards--;
label.setBackground(Color.black);
System.out.println("Removed card #" + clickedCard + "(" + card.getColorInt() + ", " + card.getValue() + ")");
if(selectedCards == 0){
resetMoveValues();
}
}
if(!useColor && !useValue && !trashCard && !placeCard){
System.out.println("Please choose move type first");
return;
}
if(clickedPlayer == currentPlayer){
if(useColor || useValue){
System.out.println("Please don't select your own cards!");
return;
} else if((trashCard || placeCard) && selectedCards == 1){
System.out.println("You already selected a card!");
return;
}
} else if(clickedPlayer != currentPlayer && (trashCard || placeCard)){
System.out.println("Please select your own cards");
return;
}
if(selectedPlayer == -1){
selectedPlayer = clickedPlayer;
chosenColor = clickedColor;
chosenValue = clickedValue;
selectedCards++;
System.out.println("Selected player #" + selectedPlayer);
label.setBackground(Color.pink);
System.out.println("Added card #" + clickedCard + "(" + intColorToText(card.getColorInt()) + ", " + card.getValue() + ")");
return;
}
if(selectedPlayer != clickedPlayer){
System.out.println("Please choose a card of the selected player or unselect all cards and choose another player.");
return;
}
if(chosenColor == -1){
chosenColor = clickedColor;
}
if(chosenValue == -1){
chosenValue = clickedValue;
}
if(label.getBackground() == Color.black){
if(useColor){
if(chosenColor == clickedColor){
if(label.getBackground() != Color.pink){
selectedCards++;
label.setBackground(Color.pink);
System.out.println("Added card #" + clickedCard + "(" + intColorToText(card.getColorInt()) + ", " + card.getValue() + ")");
}
}
} else if(useValue){
if(chosenValue == clickedValue){
if(label.getBackground() != Color.pink){
selectedCards++;
label.setBackground(Color.pink);
System.out.println("Added card #" + clickedCard + "(" + intColorToText(card.getColorInt()) + ", " + card.getValue() + ")");
}
}
}
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseClicked(MouseEvent e) {
}
});
}
mainFrame.add(playerContainer, playerSide);
}
}
private boolean hintAvailable(){
return (hints > 0);
}
private String intColorToText(int id){
String color = "";
switch(id){
case 0:
color = "green";
break;
case 1:
color = "red";
break;
case 2:
color = "yellow";
break;
case 3:
color = "white";
break;
case 4:
color = "blue";
break;
}
return color;
}
private void setWonOrLost(){
won = true;
lost = false;
for(int i=0; i<COLORS; ++i){
System.out.println("Deck " + i + ": " + deckCounter[i]);
if(deckCounter[i] != 5){
won = false;
break;
}
}
if(thunders == MAX_THUNDERS){
lost = true;
won = false;
}
if(won) System.out.println("YOU WON!");
if(lost) System.out.println("YOU LOST...");
}
private Point randomPosition(){
Point p = new Point();
p.x = random(5);
p.y = random(5);
return p;
}
private int random(int max){
return (int) (Math.random() * max);
}
private void printArray(int[][] arr){
for(int j=0; j<arr.length; ++j){
for(int k=0; k<arr[0].length; ++k){
System.out.print(arr[j][k] + ", ");
}
System.out.println("");
}
}
}