I created a simple 3 card poker game that takes in user input and determines a winner via command line using node JS. I need to convert it into a webpage where a user can input info and it will return the winner. I don't know how to go about this... below is my script.JS file
I expected to be able to just write it and connect it but I have tried a few things but i'm just a bit confused on how to accomplish that given what i've written
Here is my JS
import Hand from "./hand.js";
import prompt from "prompt-sync";
const players = prompt()("How many players?");
// // console.log(`Hey there ${players}`);
const numberOfPlayers = Number(players);
//aggregate user input
let userInput = [];
for (let i = 0; i < numberOfPlayers; i ) {
const newPrompt = prompt()(`${i} `);
userInput.push(newPrompt);
}
let hands = userInput.map((val, i) => new Hand(val, i));
hands.sort((a, b) => b.value - a.value);
let winners = [hands[0].order];
let winningValue = hands[0].value;
for (let i = 1; i < hands.length; i ) {
if (hands[i].value == winningValue) {
winners.push(hands[i].order);
} else {
break;
}
}
console.log(winners.join(", "));
And here is my hand.JS file...
const SUITS = ["h", "s", "d", "c"];
const RANKS = ["2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"];
const RANK_TO_VALUE = {
2: 2,
3: 3,
4: 4,
5: 5,
6: 6,
7: 7,
8: 8,
9: 9,
T: 10,
J: 10,
Q: 10,
K: 10,
A: 11,
};
//fresh card Hand
export default class Hand {
constructor(cards = "", order = 0) {
this.cards = cards.split(" ").map((c) => new Card(c));
this.value = this.getHandValue();
this.order = order;
}
//straight flush outcome
hasStraightFlush() {
return 100000 * (this.hasStraight() && this.hasFlush());
}
//three of a kind outcome
hasThreeOfKind() {
return (
10000 *
(this.cards[0].rank == this.cards[1].rank &&
this.cards[2].rank == this.cards[1].rank)
);
}
//straight outcome
hasStraight() {
let ranks = this.cards.map((c) => c.order);
ranks.sort();
return 1000 * (ranks[0] 2 == ranks[1] 1 && ranks[1] 1 == ranks[2]);
}
//flush outcome
hasFlush() {
return (
100 *
(this.cards[0].suit == this.cards[1].suit &&
this.cards[2].suit == this.cards[1].suit)
);
}
//pair outcome
hasPair() {
return (
20 *
((this.cards[0].rank == this.cards[1].rank ||
this.cards[2].rank == this.cards[1].rank) &&
!(
this.cards[0].rank == this.cards[1].rank &&
this.cards[2].rank == this.cards[1].rank
))
);
}
//high card outcome
hasHighCard() {
const vals = this.cards.map((c) => c.value);
vals.sort((a, b) => a - b);
return vals[vals.length - 1];
}
getHandValue() {
return Math.max(
this.hasStraightFlush(),
this.hasThreeOfKind(),
this.hasFlush(),
this.hasStraight(),
this.hasPair(),
this.hasHighCard()
);
}
}
//creates cards with suits and ranks
class Card {
constructor(input) {
this.suit = input.charAt(1);
this.rank = input.charAt(0);
this.value = RANK_TO_VALUE[this.rank];
this.order = RANKS.indexOf(this.rank);
}
// constructor(suit, rank) {
// this.suit = suit
// this.rank = rank
// }
}
//array of 52 cards as one thanks to flatmap
function freshHand() {
return SUITS.flatMap((suit) => {
return RANKS.map((rank) => {
return new Card(suit, rank);
});
});
}
CodePudding user response:
Here is a beginning
Remove the import
Remove the export default
Change prompt() to prompt (or add input with event handlers)
Fix the Cannot read properties of undefined (reading 'rank')",
(I did not "fix" it, just made it not error out by adding a conditional chaining ?
in case there is only one entry in the array)
Save in an HTML file wrapped in <script>
const SUITS = ["h", "s", "d", "c"];
const RANKS = ["2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"];
const RANK_TO_VALUE = { 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, T: 10, J: 10, Q: 10, K: 10, A: 11 };
//fresh card Hand
class Hand {
constructor(cards = "", order = 0) {
this.cards = cards.split(" ").map((c) => new Card(c));
this.value = this.getHandValue();
this.order = order;
}
//straight flush outcome
hasStraightFlush() {
return 100000 * (this.hasStraight() && this.hasFlush());
}
//three of a kind outcome
hasThreeOfKind() {
return (
10000 *
(this.cards[0].rank == this.cards[1]?.rank &&
this.cards[2].rank == this.cards[1]?.rank)
);
}
//straight outcome
hasStraight() {
let ranks = this.cards.map((c) => c.order);
ranks.sort();
return 1000 * (ranks[0] 2 == ranks[1] 1 && ranks[1] 1 == ranks[2]);
}
//flush outcome
hasFlush() {
return (
100 *
(this.cards[0].suit == this.cards[1]?.suit &&
this.cards[2]?.suit == this.cards[1]?.suit)
);
}
//pair outcome
hasPair() {
return (
20 *
((this.cards[0].rank == this.cards[1]?.rank ||
this.cards[2]?.rank == this.cards[1]?.rank) &&
!(
this.cards[0].rank == this.cards[1]?.rank &&
this.cards[2]?.rank == this.cards[1]?.rank
))
);
}
//high card outcome
hasHighCard() {
const vals = this.cards.map((c) => c.value);
vals.sort((a, b) => a - b);
return vals[vals.length - 1];
}
getHandValue() {
return Math.max(
this.hasStraightFlush(),
this.hasThreeOfKind(),
this.hasFlush(),
this.hasStraight(),
this.hasPair(),
this.hasHighCard()
);
}
}
//creates cards with suits and ranks
class Card {
constructor(input) {
this.suit = input.charAt(1);
this.rank = input.charAt(0);
this.value = RANK_TO_VALUE[this.rank];
this.order = RANKS.indexOf(this.rank);
}
// constructor(suit, rank) {
// this.suit = suit
// this.rank = rank
// }
}
//array of 52 cards as one thanks to flatmap
function freshHand() {
return SUITS.flatMap((suit) => {
return RANKS.map((rank) => {
return new Card(suit, rank);
});
});
}
/*
const players = prompt("How many players?");
// // console.log(`Hey there ${players}`);
const numberOfPlayers = Number(players);
//aggregate user input
let userInput = [];
for (let i = 0; i < numberOfPlayers; i ) {
const newPrompt = prompt(`Player ${i 1}: `);
userInput.push(newPrompt);
}
*/
window.addEventListener("DOMContentLoaded", () => {
const playButton = document.getElementById("play");
const nameDiv = document.getElementById("nameDiv");
const players = document.getElementById("players");
const playGame = () => {
const userInput = document.querySelectorAll("#nameDiv input") || 0;
if (userInput === 0) return; // nothing entered
[...userInput].map((inp, i) => console.log(inp.value));
let hands = [...userInput].map((inp, i) => new Hand(inp.value, i));
console.log(hands)
hands.sort((a, b) => b.value - a.value);
let winners = [hands[0].order];
let winningValue = hands[0].value;
for (let i = 1; i < hands.length; i ) {
if (hands[i].value == winningValue) {
winners.push(hands[i].order);
} else {
break;
}
}
output.innerHTML = winners.join(", ");
};
players.addEventListener("input", function() {
nameDiv.innerHTML = "Enter cards in the format <suit><value>: s9 is 9 of spades, hT is ten of hearts<hr/>";
nameDiv.innerHTML = Array.from({ length: this.value })
.map((_, i) => `Player ${i 1}:<input type="text" />`).join("<br/>");
})
playButton.addEventListener("click", playGame);
})
# of players <input type="number" id="players" size="2" min="1" max="4" />
<div id="nameDiv"></div>
<button type="button" id="play">Play</button>
<div id="output"></div>
CodePudding user response:
A Javascript program can run in both nodejs and browser.
In the first case, you run the program like node ./path-to-script.js
and you can add input or get output from your program directly in the terminal.
For the browser, there needs to be an HTML page that uses the script. In the shortest scenario it is simply: <script>console.log('hello world');</script>
– this is already enough HTML to run Javascript.
In your current setup, Nodejs is running a script without any connection to HTML or a browser. You run a program from terminal and you get the results printed in the terminal.
If you want to connect your script to the browser, you have for example the following two options:
- Keep using nodejs for computation and add a web-server that serves or generates HTML, which allows to submit a form with your input and your nodejs can respond to that form submission with a response.
- Stop using nodejs entirely, since the main logic of your script doesn’t depend on anything node specific, you can run the same script in the browser, and this is the suggestion that @mplungjan gave you in the other answer. Create an HTML file manually and add script code directly into it.
Choosing an option is a matter of preference.