In Cardano, all transactions are deterministic, which means you can not have unpredictable randomness, even if you inject an entropy source from, lets say and Oracle, the user who constructs the transaction will always know in advance the outcome, all variables are known at TX construction time. He then can choose to not sign/send the transaction if the outcome is undesirable.
One way to solve this problem, is to obfuscate from the user the meaning of the outcome, he will know which NFT he is getting (Asset Name), but maybe the NFT metadata is not revealed until after the NFT has been bought. Although this would require some off-chain business logic (when NFT A is bought, publish NFT A metadata). This would work better by committing to the metadata by pre-publishing a Hash of it, so the buyer knows the metadata that is being published was not changed after the fact. Sadly CIP-0025 doesn't allow to do this via smart contract because it relies on transaction metadata which cannot be read from smart contracts, so it would have to be done via an honor system.
Another approach would be to use a model similar to the current liquidity pools (I.E Minswap), The users initiate a buy order by sending ADA to a contract address, then a batcher would continuously select these orders from contract A, and execute the buy by taking the NFTs from contract B and sending it to the users. At this point, the batcher could use an Oracle as the entropy source, or the UTXO ID hashed with some secret value to pick the NFT to send to the user. This would still require some off-chain code (the batcher), but at least you could program some fairness into contracts A and B, for example, by preventing anyone to claim the money the user deposited in the buy order without sending the NFT back. (claiming the ADA in buy Order would require an NFT of a specific policy to be returned to the sender). Extra logic could be put in place to for example, allow the original sender to claim back its ADA if the order has not been executed in X amount of time.